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命令,但是需要注意一些問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM