SpringDataRedis的简单案例使用

一、SpringDataRedis环境搭建

第一步、导入坐标

<!-- 缓存 -->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.8.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-redis</artifactId>
            <version>1.7.2.RELEASE</version>
        </dependency>

第二步、Spring配置文件中注入Redis的RedisTemplate(resources/spring/applicationContext-redis.xml)

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" 
  xmlns:context="http://www.springframework.org/schema/context" 
  xmlns:mvc="http://www.springframework.org/schema/mvc" 
  xmlns:cache="http://www.springframework.org/schema/cache"
  xsi:schemaLocation="http://www.springframework.org/schema/beans   
            http://www.springframework.org/schema/beans/spring-beans.xsd   
            http://www.springframework.org/schema/context   
            http://www.springframework.org/schema/context/spring-context.xsd   
            http://www.springframework.org/schema/mvc   
            http://www.springframework.org/schema/mvc/spring-mvc.xsd 
            http://www.springframework.org/schema/cache  
            http://www.springframework.org/schema/cache/spring-cache.xsd">  
  
   <context:property-placeholder location="classpath*:properties/*.properties" />   
  
   <!-- redis 相关配置 --> 
   <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">  
     <property name="maxIdle" value="${redis.maxIdle}" />   
     <property name="maxWaitMillis" value="${redis.maxWait}" />  
     <property name="testOnBorrow" value="${redis.testOnBorrow}" />  
   </bean>  
  
   <bean id="JedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" 
       p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}" p:pool-config-ref="poolConfig"/>  
   
   <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">  
        <property name="connectionFactory" ref="JedisConnectionFactory" />  
   </bean>  
      
</beans>  

上方引入的redis的properties配置文件,一般改动一个ip即可(resources/properties/redis-config.properties)

# Redis settings 
# server IP 
redis.host=192.168.25.134
# server port 
redis.port=6379
# server pass 
redis.pass=
# use dbIndex 
redis.database=0
# \u63A7\u5236\u4E00\u4E2Apool\u6700\u591A\u6709\u591A\u5C11\u4E2A\u72B6\u6001\u4E3Aidle(\u7A7A\u95F2\u7684)\u7684jedis\u5B9E\u4F8B 
redis.maxIdle=300
# \u8868\u793A\u5F53borrow(\u5F15\u5165)\u4E00\u4E2Ajedis\u5B9E\u4F8B\u65F6\uFF0C\u6700\u5927\u7684\u7B49\u5F85\u65F6\u95F4\uFF0C\u5982\u679C\u8D85\u8FC7\u7B49\u5F85\u65F6\u95F4(\u6BEB\u79D2)\uFF0C\u5219\u76F4\u63A5\u629B\u51FAJedisConnectionException\uFF1B  
redis.maxWait=3000
# \u5728borrow\u4E00\u4E2Ajedis\u5B9E\u4F8B\u65F6\uFF0C\u662F\u5426\u63D0\u524D\u8FDB\u884Cvalidate\u64CD\u4F5C\uFF1B\u5982\u679C\u4E3Atrue\uFF0C\u5219\u5F97\u5230\u7684jedis\u5B9E\u4F8B\u5747\u662F\u53EF\u7528\u7684  
redis.testOnBorrow=true

当前SpringDataRedis环境已经搭建完毕,以下代码在RedisTest.java类中通过单元测试进行。

以下测试通过Spring整合junit进行。

准备:测试类SpringDataRedis

@RunWith(SpringJunit4ClassRunner.class)
@ContextConfiguration("classpath:spring/applicationContext-redis.xml")
public class SpringDataRedis{
    @Autowired
    private RedisTemplate redisTemplate;
   //测试代码区
}

说明:下方的存取指的是通过一个key对以该key为依据存入redis值和取出redis中的值。

二、SpringDataRedis的使用

1、String类型的数据存取

1.1 set进一个值

@Test
public void testSet(){
    redisTemplate.boundValueOps("str").set("我是被存储的字符串!");
}

1.2 get到一个值

@Test
public void testGet(){
    String result=redisTemplate.boundValueOps("str").get();
    System.out.println(result);
}

1.3 delete一个key及其它所指向的值,所有类型都可以用

@Test
public void testDelete(){
    //此操作执行之后再获取该key指向的值时Java中的代码得到的时null
    redisTemplate.delete("str");
}

拓展:redis中设置键值的存活时间

2、Hash类型的存取

2.1 put一个值到HashMap中

@Test
public void testPush(){
    //Hash类型其实就是HashMap
  redisTemplate.boundHashOps("group").put("member1","HUAWEI");
  redisTemplate.boundHashOps("group").put("member2","Alibaba");
}

2.2 get到一个指定key的值

@Test
public void testGet(){
    //所有存到redis中的对象全部需要序列化,并且取值时需要强转成自己需要的类型
    String member1=(String)redisTemplate.boundHashOps("group").get("member1");
    String member2=(String)redisTemplate.boundHashOps("group").get("member2");
    System.out.println(member1);
    System.out.println(member2);
}

2.3 获取被绑定key的所有键/大小/全部值

@Test
public void testApi(){
    redisTemplate.boundHashOps("group").keys();//返回一个Set,因为不允许重复
    redisTemplate.boundHashOps("group").values();//返回一个List,因为可以重复
    redisTemplate.boundHashOps("group").size();//返回一个Long数值
}

2.4 从Hash中删除键值

@Test
public void testDelete(){
    redisTemplate.boundHashOps("group").delete("member1");//删除指定成员的键值
    redisTemplate.boundHashOps("group").delete();//删除Hash中指定key下的所有值
}

3、List类型的存取

3.1 push一个值到List中

@Test
public void testPush(){
    redisTemplate.boundListOps("hero").leftPush("乔峰");
    redisTemplate.boundListOps("hero").leftPush("扫地僧");
    redisTemplate.boundListOps("hero").leftPush("孙悟空");
}

3.2 pop出一个值

@Test
public void testPop(){
    redisTemplate.boundListOps("hero").rightPop();//此操作执行之后会从list中删除一个
    redisTemplate.boundListOps("hero").rightPop(1,TimeUnit枚举变量);//每一个间隔弹一个
    redisTemplate.boundListOps("hero").range(0,-1);//返回所有的值,但是不清除
}

3.3 remove删除操作

@Test
public void testRemove(){
   
    //redisTemplate.delete("hero");//这是删除全部的值
    redisTemplate.boundListOps("hero").remove(删除个数,要被删除的值);//有API可以设置删除的方向
}

4、Set类型的存取

4.1 add实现添加值

@Test
public void testAdd(){
    //set不准有重复的key
    redisTemplate.boundSetOps("character").add("孙行者");
    redisTemplate.boundSetOps("character").add("孙行者");
    redisTemplate.boundSetOps("character").add("猪悟能");
    redisTemplate.boundSetOps("character").add("沙悟净");
    redisTemplate.boundSetOps("character").add("孙悟空");
    redisTemplate.boundSetOps("character").add("唐玄奘");
}

4.2 获取Set里面的值

@Test
public void testMember(){
    Set<String> characters=redisTemplate.boundSetOps("character").members();//会返回一个Set
    for(String character : characters){
        System.out.println(s);
    }
    
    Boolean member=redisTemplate.boundSetOps("character").isMember("如来");
    //还有api如,取出一个随机的值randomMember(),取出两个diff差集。另外set也可以pop()一个值出来。
}

4.3 remove指定删除

@Test
public void testRemove(){
    redisTemplate.boundSetOps("character").remove("唐玄奘");//删除指定的值
    redisTemplate.boundSetOps("character").delete();//清空所有
}

5、ZSet类型的存取

ZSet的有序是依据分值实现的,相当于权值。

5.1 add值到ZSet中

@Test
public void testAdd(){
    //key相同时为修改更新
    redisTemplate.boundZSetOps("role").add("人民",10);
    redisTemplate.boundZSetOps("role").add("公民",20);
    redisTemplate.boundZSetOps("role").add("官员",30);
    redisTemplate.boundZSetOps("role").add("洋人",40);
} 

5.2 range取出所有的值

返回值仍为Set

@Test
public void testRange(){
    //不带分值的获取
    Set<String> roles= redisTemplate.boundZSetOps("role").range(0,,-1);
    for(String role:roles){
        System.out.println(role);
    }
    //不带分的获取全部
    Set<TypedTupl> rolesTypeTupl=redisTemplate.boundZSetOps("role").rangeWithScore(0,-1)//指定获取的所有
    for(TypedTupl role : rolesTypeTupl){
        System.out.println(role.getValue+"@@@@@@"+role.getScore());
    }
    //带分的获取
    Set<TypedTupl> rolesTypeTuplWithScore=redisTemplate.boundZSetOps("role").rangeByScoreWithScore(10,40)//指定score范围
    for(TypedTupl role : rolesTypeTuplWithScore){
        System.out.println(role.getValue+"@@@@@@"+role.getScore());
    }
    
}

拓展:

1、redis的增、删、改、查中对于修改操作,在redis中key值相同时增加既是修改。

2、设置key的存活【expire(Long unit,TimeUnit timeUnit)//是枚举变量】

---【完】---

拓展:在redis客户端(黑窗口)操作redis的基本命令

参考:https://juejin.im/post/5ad6e4066fb9a028d82c4b66

 

Redis常见数据结构使用场景

1. String

常用命令: set,get,decr,incr,mget 等。

String数据结构是简单的key-value类型,value其实不仅可以是String,也可以是数字。 常规key-value缓存应用; 常规计数:微博数,粉丝数等。

2.Hash

常用命令: hget,hset,hgetall 等。

Hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。 比如我们可以Hash数据结构来存储用户信息,商品信息等等。

举个例子: 最近做的一个电商网站项目的首页就使用了redis的hash数据结构进行缓存,因为一个网站的首页访问量是最大的,所以通常网站的首页可以通过redis缓存来提高性能和并发量。我用jedis客户端来连接和操作我搭建的redis集群或者单机redis,利用jedis可以很容易的对redis进行相关操作,总的来说从搭一个简单的集群到实现redis作为缓存的整个步骤不难。感兴趣的可以看我昨天写的这篇文章:

《一文轻松搞懂redis集群原理及搭建与使用》: juejin.im/post/5ad54d…

3.List

常用命令: lpush,rpush,lpop,rpop,lrange等

list就是链表,Redis list的应用场景非常多,也是Redis最重要的数据结构之一,比如微博的关注列表,粉丝列表,最新消息排行等功能都可以用Redis的list结构来实现。

Redis list的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销。

4.Set

常用命令: sadd,spop,smembers,sunion 等

set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的。 当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。

在微博应用中,可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。Redis可以非常方便的实现如共同关注、共同喜好、二度好友等功能。

5.Sorted Set

常用命令: zadd,zrange,zrem,zcard等

和set相比,sorted set增加了一个权重参数score,使得集合中的元素能够按score进行有序排列。

举例: 在直播系统中,实时排行信息包含直播间在线用户列表,各种礼物排行榜,弹幕消息(可以理解为按消息维度的消息排行榜)等信息,适合使用Redis中的SortedSet结构进行存储。

MySQL里有2000w数据,Redis中只存20w的数据,如何保证Redis中的数据都是热点数据(redis有哪些数据淘汰策略???)

   相关知识:redis 内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略(回收策略)。redis 提供 6种数据淘汰策略:

  1. volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
  2. volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
  3. volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
  4. allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
  5. allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
  6. no-enviction(驱逐):禁止驱逐数据

Redis的并发竞争问题如何解决?

Redis为单进程单线程模式,采用队列模式将并发访问变为串行访问。Redis本身没有锁的概念,Redis对于多个客户端连接并不存在竞争,但是在Jedis客户端对Redis进行并发访问时会发生连接超时、数据转换错误、阻塞、客户端关闭连接等问题,这些问题均是由于客户端连接混乱造成。对此有2种解决方法:

 1.客户端角度,为保证每个客户端间正常有序与Redis进行通信,对连接进行池化,同时对客户端读写Redis操作采用内部锁synchronized。   2.服务器角度,利用setnx实现锁。

 注:对于第一种,需要应用程序自己处理资源的同步,可以使用的方法比较通俗,可以使用synchronized也可以使用lock;第二种需要用到Redis的setnx命令,但是需要注意一些问题。

posted @ 2019-07-16 23:33  手握钢叉的猹  阅读(2064)  评论(0编辑  收藏  举报