RedisTemplate介紹和用法


RedisTemplate介紹和用法

Redis 介紹

Spring-data-redis是spring大家族的一部分,提供了在srping應用中通過簡單的配置訪問redis服務,對reids底層開發包(Jedis, JRedis, and RJC)進行了高度封裝,RedisTemplate提供了redis各種操作、異常處理及序列化,支持發布訂閱,並對spring 3.1 cache進行了實現。
官網:http://projects.spring.io/spring-data-redis/
項目地址:https://github.com/spring-projects/spring-data-redis

Redis 可以存儲鍵與5種不同數據結構類型之間的映射,這5種數據結構類型分別為String(字符串)、List(列表)、Set(集合)、Hash(散列)和 Zset(有序集合)。

spring-data-redis功能介紹

jedis客戶端在編程實施方面存在如下不足:

  1. connection管理缺乏自動化,connection-pool的設計缺少必要的容器支持。
  2. 數據操作需要關注“序列化”/“反序列化”,因為jedis的客戶端API接受的數據類型為string和byte,對結構化數據(json,xml,pojo等)操作需要額外的支持。
  3. 事務操作純粹為硬編碼。
  4. pub/sub功能,缺乏必要的設計模式支持,對於開發者而言需要關注的太多。

spring-data-redis針對jedis提供了如下功能:

  • 1.連接池自動管理,提供了一個高度封裝的“RedisTemplate”類

  • 2.針對jedis客戶端中大量api進行了歸類封裝,將同一類型操作封裝為operation接口

    ValueOperations:簡單K-V操作
    SetOperations:set類型數據操作
    ZSetOperations:zset類型數據操作
    HashOperations:針對map類型的數據操作
    ListOperations:針對list類型的數據操作
    
  • 3.提供了對key的“bound”(綁定)便捷化操作API,可以通過bound封裝指定的key,然后進行一系列的操作而無須“顯式”的再次指定Key,即

    BoundKeyOperations:
    BoundValueOperations
    BoundSetOperations
    BoundListOperations
    BoundSetOperations
    BoundHashOperations
    
  • 4.將事務操作封裝,有容器控制。

  • 5.針對數據的“序列化/反序列化”,提供了多種可選擇策略(RedisSerializer)

    • JdkSerializationRedisSerializer:POJO對象的存取場景,使用JDK本身序列化機制,將pojo類通過ObjectInputStream/ObjectOutputStream進行序列化操作,最終redis-server中將存儲字節序列。是目前最常用的序列化策略。

    • StringRedisSerializer:Key或者value為字符串的場景,根據指定的charset對數據的字節序列編碼成string,是“new String(bytes, charset)”和“string.getBytes(charset)”的直接封裝。是最輕量級和高效的策略。

    • JacksonJsonRedisSerializer:jackson-json工具提供了javabean與json之間的轉換能力,可以將pojo實例序列化成json格式存儲在redis中,也可以將json格式的數據轉換成pojo實例。因為jackson工具在序列化和反序列化時,需要明確指定Class類型,因此此策略封裝起來稍微復雜。【需要jackson-mapper-asl工具支持】

    • OxmSerializer:提供了將javabean與xml之間的轉換能力,目前可用的三方支持包括jaxb,apache-xmlbeans;redis存儲的數據將是xml工具。不過使用此策略,編程將會有些難度,而且效率最低;不建議使用。【需要spring-oxm模塊的支持】

      針對“序列化和發序列化”中JdkSerializationRedisSerializer和StringRedisSerializer是最基礎的策略,原則上,我們可以將數據存儲為任何格式以便應用程序存取和解析(其中應用包括app,hadoop等其他工具),不過在設計時仍然不推薦直接使用“JacksonJsonRedisSerializer”和“OxmSerializer”,因為無論是json還是xml,他們本身仍然是String。如果你的數據需要被第三方工具解析,那么數據應該使用StringRedisSerializer而不是JdkSerializationRedisSerializer。如果你的數據格式必須為json或者xml,那么在編程級別,在redisTemplate配置中仍然使用StringRedisSerializer,在存儲之前或者讀取之后,使用“SerializationUtils”工具轉換轉換成json或者xml

  • 6.基於設計模式,和JMS開發思路,將pub/sub的API設計進行了封裝,使開發更加便捷。

  • 7.spring-data-redis中,並沒有對sharding提供良好的封裝,如果你的架構是基於sharding,那么你需要自己去實現,這也是sdr和jedis相比,唯一缺少的特性。

String操作

set void set(K key, V value);
添加獲取數據

redisTemplate.opsForValue().set("numTest_1","123");//設置key和value
String getRedisStr = redisTemplate.opsForValue().get("numTest_1");//根據key讀value
System.out.println("getRedisStr---------"+getRedisStr);//123

set void set(K key, V value, long timeout, TimeUnit unit);
設置數據有效期

redisTemplate.opsForValue().set("numTest_2","456",10, TimeUnit.SECONDS);
String getRedisStrTime = redisTemplate.opsForValue().get("numTest_2");//設置的是10秒失效,十秒之內查詢有結果,十秒之后返回為null
System.out.println("getRedisStrTime---------"+getRedisStrTime);//456
//        TimeUnit.DAYS          //天
//        TimeUnit.HOURS         //小時
//        TimeUnit.MINUTES       //分鍾
//        TimeUnit.SECONDS       //秒
//        TimeUnit.MILLISECONDS  //毫秒

set void set(K key, V value, long offset);
根據key設置value指定下標字符

redisTemplate.opsForValue().set("keyTest_1","hello world");
//覆寫(overwrite)給定 key 所儲存的字符串值,從偏移量 offset 開始  6:偏移下標
redisTemplate.opsForValue().set("keyTest_1","redis", 6);
String getRedisOffsetStr = redisTemplate.opsForValue().get("keyTest_1");
System.out.println("getRedisOffsetStr---------"+getRedisOffsetStr);//hello redis

get V get(Object key);
Get操作

template.opsForValue().set("key","hello world");
System.out.println("---------"+template.opsForValue().get("key"));//hello world

getAndSet V getAndSet(K key, V value);
設置鍵的字符串值並返回其舊值

redisTemplate.opsForValue().set("SetTest","test");
String getRedisAndSet = redisTemplate.opsForValue().getAndSet("SetTest", "test2");
System.out.println("getRedisAndSet---------"+getRedisAndSet);//test

append Integer append(K key, String value);
根據key拼接value的值,如果被拼接的key沒值則為空字符串

redisTemplate.opsForValue().append("test","Hello");	
String getRedisAppend_1 = redisTemplate.opsForValue().get("test");
System.out.println("getRedisAppend_1---------"+getRedisAppend_1);//Hello

redisTemplate.opsForValue().append("test","world");
String getRedisAppend_2 = redisTemplate.opsForValue().get("test"); 
System.out.println("getRedisAppend_2---------"+getRedisAppend_2);//Helloworld

size Long size(K key);
根據key獲取value的長度

redisTemplate.opsForValue().set("key","hello world");
Long getRedisStrSize = redisTemplate.opsForValue().size("key");
System.out.println("getRedisStrSize---------"+getRedisStrSize);//11

List操作

Long size(K key);
返回存儲在鍵中的列表的長度。如果鍵不存在,則將其解釋為空列表,並返回0。當key存儲的值不是列表時返回錯誤。

System.out.println(template.opsForList().size("list"));//0

Long leftPush(K key, V value);
(從左邊插入)將所有指定的值插入存儲在鍵的列表的頭部。如果鍵不存在,則在執行推送操作之前將其創建為空列表。

template.opsForList().leftPush("list","java");
template.opsForList().leftPush("list","python");
template.opsForList().leftPush("list","c++");
//返回的結果為推送操作后的列表長度,推送三次,分次為123

Long leftPushAll(K key, V... values);
(從左邊插入)批量把一個數組插入到列表中

String[] strs = new String[]{"1","2","3"};
template.opsForList().leftPushAll("list",strs);
System.out.println(template.opsForList().range("list",0,-1));//[3, 2, 1]

Long rightPush(K key, V value);
(從右邊插入)將所有指定的值插入存儲在鍵的列表的頭部。如果鍵不存在,則在執行推送操作之前將其創建為空列表。(從右邊插入)

template.opsForList().rightPush("listRight","java");
template.opsForList().rightPush("listRight","python");
template.opsForList().rightPush("listRight","c++");
//返回的結果為推送操作后的列表長度,推送三次,分次為123

Long rightPushAll(K key, V... values);

(從右邊插入)批量把一個數組插入到列表中

String[] strs = new String[]{"1","2","3"};
template.opsForList().rightPushAll("list",strs);
System.out.println(template.opsForList().range("list",0,-1));//[1, 2, 3]

void set(K key, long index, V value);
在列表中index的位置設置value值

System.out.println(template.opsForList().range("listRight",0,-1));
template.opsForList().set("listRight",1,"setValue");
System.out.println(template.opsForList().range("listRight",0,-1));
//[java, python, oc, c++]
//[java, setValue, oc, c++]

Long remove(K key, long count, Object value);
從存儲在鍵中的列表中刪除等於值的元素的第一個計數事件。
計數參數以下列方式影響操作:
count> 0:刪除等於從頭到尾移動的值的元素。
count <0:刪除等於從尾到頭移動的值的元素。
count = 0:刪除等於value的所有元素。

System.out.println(template.opsForList().range("listRight",0,-1));
template.opsForList().remove("listRight",1,"setValue");//將刪除列表中存儲的列表中第一次出現的“setValue”。
System.out.println(template.opsForList().range("listRight",0,-1));
[java, setValue, oc, c++]
[java, oc, c++]

V index(K key, long index);
根據下標獲取列表中的值,下標是從0開始的,-1為獲取全部

System.out.println(template.opsForList().range("listRight",0,-1));
System.out.println(template.opsForList().index("listRight",2));
//[java, oc, c++]
//c++

V leftPop(K key);
彈出最左邊的元素,彈出之后該值在列表中將不復存在

System.out.println(template.opsForList().range("list",0,-1));
System.out.println(template.opsForList().leftPop("list"));
System.out.println(template.opsForList().range("list",0,-1));
//[c++, python, oc, java, c#]
//c++
//[python, oc, java, c#]

V rightPop(K key);
彈出最右邊的元素,彈出之后該值在列表中將不復存在

System.out.println(template.opsForList().range("list",0,-1));
System.out.println(template.opsForList().rightPop("list"));
System.out.println(template.opsForList().range("list",0,-1));
//[python, oc, java, c#]
//c#
//[python, oc, java]

Hash操作

Long delete(H key, Object... hashKeys);
刪除給定的哈希hashKeys

System.out.println(template.opsForHash().delete("redisHash","name"));
System.out.println(template.opsForHash().entries("redisHash"));
//1
//{class=6, age=28.1}

Boolean hasKey(H key, Object hashKey);
判斷哈希hashKey是否存在

System.out.println(template.opsForHash().hasKey("redisHash","666"));
System.out.println(template.opsForHash().hasKey("redisHash","777"));
//true
//false

HV get(H key, Object hashKey);
從鍵中的哈希獲取給定hashKey的值

System.out.println(template.opsForHash().get("redisHash","age"));
//26

Set keys(H key);
獲取key所對應的散列表的key

System.out.println(template.opsForHash().keys("redisHash"));
//redisHash所對應的散列表為{class=1, name=666, age=27}
//[name, class, age]

Long size(H key);
獲取key所對應的散列表的大小個數

System.out.println(template.opsForHash().size("redisHash"));
//redisHash所對應的散列表為{class=1, name=666, age=27}
//3

void putAll(H key, Map<? extends HK, ? extends HV> m);
使用m中提供的多個散列字段設置到key對應的散列表中

Map<String,Object> testMap = new HashMap();
testMap.put("name","666");
testMap.put("age",27);
testMap.put("class","1");
template.opsForHash().putAll("redisHash1",testMap);
System.out.println(template.opsForHash().entries("redisHash1"));
//{class=1, name=jack, age=27}

void put(H key, HK hashKey, HV value);
設置散列hashKey的值

template.opsForHash().put("redisHash","name","666");
template.opsForHash().put("redisHash","age",26);
template.opsForHash().put("redisHash","class","6");
System.out.println(template.opsForHash().entries("redisHash"));
//{age=26, class=6, name=666}

List values(H key);
獲取整個哈希存儲的值根據密鑰

System.out.println(template.opsForHash().values("redisHash"));
//[tom, 26, 6]

Map<HK, HV> entries(H key);
獲取整個哈希存儲根據密鑰

System.out.println(template.opsForHash().entries("redisHash"));
{age=26, class=6, name=tom}

Cursor<Map.Entry<HK, HV>> scan(H key, ScanOptions options);
使用Cursor在key的hash中迭代,相當於迭代器。

Cursor<Map.Entry<Object, Object>> curosr = template.opsForHash().scan("redisHash",ScanOptions.ScanOptions.NONE);
while(curosr.hasNext()){
    Map.Entry<Object, Object> entry = curosr.next();
    System.out.println(entry.getKey()+":"+entry.getValue());
}
//age:27
//class:6
//name:666

Set操作

Long add(K key, V... values);
無序集合中添加元素,返回添加個數
也可以直接在add里面添加多個值 如:template.opsForSet().add("setTest","aaa","bbb")

String[] strs= new String[]{"str1","str2"};
System.out.println(template.opsForSet().add("setTest", strs));
//2

Long remove(K key, Object... values);
移除集合中一個或多個成員

String[] strs = new String[]{"str1","str2"};
System.out.println(template.opsForSet().remove("setTest",strs));
//2

V pop(K key);
移除並返回集合中的一個隨機元素

System.out.println(template.opsForSet().pop("setTest"));
System.out.println(template.opsForSet().members("setTest"));
//bbb
//[aaa, ccc]

Boolean move(K key, V value, K destKey);
將 member 元素從 source 集合移動到 destination 集合

template.opsForSet().move("setTest","aaa","setTest2");
System.out.println(template.opsForSet().members("setTest"));
System.out.println(template.opsForSet().members("setTest2"));
//[ccc]
//[aaa]

Long size(K key);
無序集合的大小長度

System.out.println(template.opsForSet().size("setTest"));
//1

Set members(K key);
返回集合中的所有成員

System.out.println(template.opsForSet().members("setTest"));
//[ddd, bbb, aaa, ccc]

Cursor scan(K key, ScanOptions options);
遍歷set

Cursor<Object> curosr = template.opsForSet().scan("setTest", ScanOptions.NONE);
  while(curosr.hasNext()){
     System.out.println(curosr.next());
  }
//ddd
//bbb
//aaa
//ccc

ZSet操作

Boolean add(K key, V value, double score);
新增一個有序集合,存在的話為false,不存在的話為true

System.out.println(template.opsForZSet().add("zset1","zset-1",1.0));
//true

Long add(K key, Set<TypedTuple > tuples);
新增一個有序集合

ZSetOperations.TypedTuple<Object> objectTypedTuple1 = new DefaultTypedTuple<>("zset-5",9.6);
ZSetOperations.TypedTuple<Object> objectTypedTuple2 = new DefaultTypedTuple<>("zset-6",9.9);
Set<ZSetOperations.TypedTuple<Object>> tuples = new HashSet<ZSetOperations.TypedTuple<Object>>();
tuples.add(objectTypedTuple1);
tuples.add(objectTypedTuple2);
System.out.println(template.opsForZSet().add("zset1",tuples));
System.out.println(template.opsForZSet().range("zset1",0,-1));
//[zset-1, zset-2, zset-3, zset-4, zset-5, zset-6]

Long remove(K key, Object... values);
從有序集合中移除一個或者多個元素

System.out.println(template.opsForZSet().range("zset1",0,-1));
System.out.println(template.opsForZSet().remove("zset1","zset-6"));
System.out.println(template.opsForZSet().range("zset1",0,-1));
//[zset-1, zset-2, zset-3, zset-4, zset-5, zset-6]
//1
//[zset-1, zset-2, zset-3, zset-4, zset-5]

Long rank(K key, Object o);
返回有序集中指定成員的排名,其中有序集成員按分數值遞增(從小到大)順序排列

System.out.println(template.opsForZSet().range("zset1",0,-1));
System.out.println(template.opsForZSet().rank("zset1","zset-2"));
//[zset-2, zset-1, zset-3, zset-4, zset-5]
//0   表明排名第一

Set range(K key, long start, long end);
通過索引區間返回有序集合成指定區間內的成員,其中有序集成員按分數值遞增(從小到大)順序排列

System.out.println(template.opsForZSet().range("zset1",0,-1));
//[zset-2, zset-1, zset-3, zset-4, zset-5]

Long count(K key, double min, double max);
通過分數返回有序集合指定區間內的成員個數

System.out.println(template.opsForZSet().rangeByScore("zset1",0,5));
System.out.println(template.opsForZSet().count("zset1",0,5));
//[zset-2, zset-1, zset-3]
//3

Long size(K key);
獲取有序集合的成員數,內部調用的就是zCard方法

System.out.println(template.opsForZSet().size("zset1"));
//6

Double score(K key, Object o);
獲取指定成員的score值

System.out.println(template.opsForZSet().score("zset1","zset-1"));
//2.2

Long removeRange(K key, long start, long end);
移除指定索引位置的成員,其中有序集成員按分數值遞增(從小到大)順序排列

System.out.println(template.opsForZSet().range("zset2",0,-1));
System.out.println(template.opsForZSet().removeRange("zset2",1,2));
System.out.println(template.opsForZSet().range("zset2",0,-1));
//[zset-1, zset-2, zset-3, zset-4]
//2
//[zset-1, zset-4]

Cursor<TypedTuple > scan(K key, ScanOptions options);
遍歷zset

Cursor<ZSetOperations.TypedTuple<Object>> cursor = template.opsForZSet().scan("zzset1", ScanOptions.NONE);
    while (cursor.hasNext()){
       ZSetOperations.TypedTuple<Object> item = cursor.next();
       System.out.println(item.getValue() + ":" + item.getScore());
    }
//zset-1:1.0
//zset-2:2.0
//zset-3:3.0
//zset-4:6.0

原文鏈接:https://blog.csdn.net/javaxiaibai0414/article/details/88666453


免責聲明!

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



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