• 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
    # u63A7u5236u4E00u4E2Apoolu6700u591Au6709u591Au5C11u4E2Au72B6u6001u4E3Aidle(u7A7Au95F2u7684)u7684jedisu5B9Eu4F8B 
    redis.maxIdle=300
    # u8868u793Au5F53borrow(u5F15u5165)u4E00u4E2Ajedisu5B9Eu4F8Bu65F6uFF0Cu6700u5927u7684u7B49u5F85u65F6u95F4uFF0Cu5982u679Cu8D85u8FC7u7B49u5F85u65F6u95F4(u6BEBu79D2)uFF0Cu5219u76F4u63A5u629Bu51FAJedisConnectionExceptionuFF1B  
    redis.maxWait=3000
    # u5728borrowu4E00u4E2Ajedisu5B9Eu4F8Bu65F6uFF0Cu662Fu5426u63D0u524Du8FDBu884Cvalidateu64CDu4F5CuFF1Bu5982u679Cu4E3AtrueuFF0Cu5219u5F97u5230u7684jedisu5B9Eu4F8Bu5747u662Fu53EFu7528u7684  
    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命令,但是需要注意一些问题。

  • 相关阅读:
    vue 样式使用总结
    安卓内嵌H5只展示部分静态页面
    Excel 2016入门与提高
    Oracle Exadata技术详解
    计算机网络基础
    Photoshop扁平化平面设计手册
    C程序设计伴侣——帮你更好地理解谭浩强老师的那本书以及更多!
    中文版Project 2007实用教程
    新手学CorelDRAW X8商业设计200+
    Altium Designer 17电路设计与仿真从入门到精通
  • 原文地址:https://www.cnblogs.com/kitor/p/11198306.html
Copyright © 2020-2023  润新知