Redis 數據結構簡介
Redis 可以存儲鍵與5種不同數據結構類型之間的映射,這5種數據結構類型分別為String(字符串)、List(列表)、Set(集合)、Hash(散列)和 Zset(有序集合)。
下面來對這5種數據結構類型作簡單的介紹:
| 結構類型 | 結構存儲的值 | 結構的讀寫能力 |
|---|---|---|
| String | 可以是字符串、整數或者浮點數 | 對整個字符串或者字符串的其中一部分執行操作;對象和浮點數執行自增(increment)或者自減(decrement) |
| List | 一個鏈表,鏈表上的每個節點都包含了一個字符串 | 從鏈表的兩端推入或者彈出元素;根據偏移量對鏈表進行修剪(trim);讀取單個或者多個元素;根據值來查找或者移除元素 |
| Set | 包含字符串的無序收集器(unorderedcollection),並且被包含的每個字符串都是獨一無二的、各不相同 | 添加、獲取、移除單個元素;檢查一個元素是否存在於某個集合中;計算交集、並集、差集;從集合里賣弄隨機獲取元素 |
| Hash | 包含鍵值對的無序散列表 | 添加、獲取、移除單個鍵值對;獲取所有鍵值對 |
| Zset | 字符串成員(member)與浮點數分值(score)之間的有序映射,元素的排列順序由分值的大小決定 | 添加、獲取、刪除單個元素;根據分值范圍(range)或者成員來獲取元素 |
Redis 5種數據結構的概念大致介紹到這邊,下面將結合Spring封裝的RedisTemplate來對這5種數據結構的運用進行演示
RedisTemplate介紹
spring 封裝了 RedisTemplate 對象來進行對redis的各種操作,它支持所有的 redis 原生的 api。
RedisTemplate在spring代碼中的結構如下:
org.springframework.data.redis.core Class RedisTemplate<K,V> java.lang.Object org.springframework.data.redis.core.RedisAccessor org.springframework.data.redis.core.RedisTemplate<K,V>
Type Parameters:
K
- the Redis key type against which the template works (usually a String)
模板中的Redis key的類型(通常為String)如:RedisTemplate<String, Object>
注意:如果沒特殊情況,切勿定義成RedisTemplate<Object, Object>,否則根據里氏替換原則,使用的時候會造成類型錯誤 。
V - the Redis value type against which the template works
模板中的Redis value的類型
RedisTemplate中定義了對5種數據結構操作
redisTemplate.opsForValue();//操作字符串 redisTemplate.opsForHash();//操作hash redisTemplate.opsForList();//操作list redisTemplate.opsForSet();//操作set redisTemplate.opsForZSet();//操作有序set
StringRedisTemplate與RedisTemplate
-
兩者的關系是StringRedisTemplate繼承RedisTemplate。
-
兩者的數據是不共通的;也就是說StringRedisTemplate只能管理StringRedisTemplate里面的數據,RedisTemplate只能管理RedisTemplate中的數據。
-
SDR默認采用的序列化策略有兩種,一種是String的序列化策略,一種是JDK的序列化策略。
StringRedisTemplate默認采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的。
RedisTemplate默認采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。
RedisTemplate配置如下:
@Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); RedisTemplate<String, Object> template = new RedisTemplate<String, Object>(); template.setConnectionFactory(redisConnectionFactory); template.setKeySerializer(jackson2JsonRedisSerializer); template.setValueSerializer(jackson2JsonRedisSerializer); template.setHashKeySerializer(jackson2JsonRedisSerializer); template.setHashValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; }
Redis的String數據結構 (推薦使用StringRedisTemplate)
注意:如果使用RedisTemplate需要更改序列化方式
RedisSerializer<String> stringSerializer = new StringRedisSerializer(); template.setKeySerializer(stringSerializer ); template.setValueSerializer(stringSerializer ); template.setHashKeySerializer(stringSerializer ); template.setHashValueSerializer(stringSerializer );
public interface ValueOperations<K,V>
Redis operations for simple (or in Redis terminology 'string') values.
ValueOperations可以對String數據結構進行操作:
- set void set(K key, V value);
使用:redisTemplate.opsForValue().set("name","tom");
結果:redisTemplate.opsForValue().get("name") 輸出結果為tom
- set void set(K key, V value, long timeout, TimeUnit unit);
使用:redisTemplate.opsForValue().set("name","tom",10, TimeUnit.SECONDS);
結果:redisTemplate.opsForValue().get("name")由於設置的是10秒失效,十秒之內查詢有結果,十秒之后返回為null
set void set(K key, V value, long offset);該方法是用 value 參數覆寫(overwrite)給定 key 所儲存的字符串值,從偏移量 offset 開始
使用:template.opsForValue().set("key","hello world");
template.opsForValue().set("key","redis", 6);
System.out.println("***************"+template.opsForValue().get("key"));
結果:***************hello redis
- setIfAbsent Boolean setIfAbsent(K key, V value);
使用:System.out.println(template.opsForValue().setIfAbsent("multi1","multi1"));//false multi1之前已經存在
System.out.println(template.opsForValue().setIfAbsent("multi111","multi111"));//true multi111之前不存在
結果:false
true
- multiSet void multiSet(Map<? extends K, ? extends V> m);為多個鍵分別設置它們的值
使用:Map<String,String> maps = new HashMap<String, String>(); maps.put("multi1","multi1"); maps.put("multi2","multi2"); maps.put("multi3","multi3"); template.opsForValue().multiSet(maps); List<String> keys = new ArrayList<String>(); keys.add("multi1"); keys.add("multi2"); keys.add("multi3"); System.out.println(template.opsForValue().multiGet(keys)); 結果:[multi1, multi2, multi3]
- multiSetIfAbsent Boolean multiSetIfAbsent(Map<? extends K, ? extends V> m);為多個鍵分別設置它們的值,如果存在則返回false,不存在返回true
使用:Map<String,String> maps = new HashMap<String, String>(); maps.put("multi11","multi11"); maps.put("multi22","multi22"); maps.put("multi33","multi33"); Map<String,String> maps2 = new HashMap<String, String>(); maps2.put("multi1","multi1"); maps2.put("multi2","multi2"); maps2.put("multi3","multi3"); System.out.println(template.opsForValue().multiSetIfAbsent(maps)); System.out.println(template.opsForValue().multiSetIfAbsent(maps2)); 結果:true false
- get V get(Object key);
使用:template.opsForValue().set("key","hello world");
System.out.println("***************"+template.opsForValue().get("key"));
結果:***************hello world
- getAndSet V getAndSet(K key, V value);設置鍵的字符串值並返回其舊值
使用:template.opsForValue().set("getSetTest","test");
System.out.println(template.opsForValue().getAndSet("getSetTest","test2"));
結果:test
- multiGet List<V> multiGet(Collection<K> keys);為多個鍵分別取出它們的值
使用:Map<String,String> maps = new HashMap<String, String>(); maps.put("multi1","multi1"); maps.put("multi2","multi2"); maps.put("multi3","multi3"); template.opsForValue().multiSet(maps); List<String> keys = new ArrayList<String>(); keys.add("multi1"); keys.add("multi2"); keys.add("multi3"); System.out.println(template.opsForValue().multiGet(keys)); 結果:[multi1, multi2, multi3]
- increment Long increment(K key, long delta);支持整數
使用:template.opsForValue().increment("increlong",1);
System.out.println("***************"+template.opsForValue().get("increlong"));
結果:***************1
- increment Double increment(K key, double delta);也支持浮點數
使用:template.opsForValue().increment("increlong",1.2);
System.out.println("***************"+template.opsForValue().get("increlong"));
結果:***************2.2
- append Integer append(K key, String value);如果key已經存在並且是一個字符串,則該命令將該值追加到字符串的末尾。
- 如果鍵不存在,則它被創建並設置為空字符串,因此APPEND在這種特殊情況下將類似於SET。
使用:template.opsForValue().append("appendTest","Hello");
System.out.println(template.opsForValue().get("appendTest"));
template.opsForValue().append("appendTest","world");
System.out.println(template.opsForValue().get("appendTest"));
結果:Hello
Helloworld
- get String get(K key, long start, long end);截取key所對應的value字符串
使用:appendTest對應的value為Helloworld System.out.println("*********"+template.opsForValue().get("appendTest",0,5)); 結果:*********Hellow 使用:System.out.println("*********"+template.opsForValue().get("appendTest",0,-1)); 結果:*********Helloworld 使用:System.out.println("*********"+template.opsForValue().get("appendTest",-3,-1)); 結果:*********rld
- size Long size(K key);返回key所對應的value值得長度
使用:template.opsForValue().set("key","hello world");
System.out.println("***************"+template.opsForValue().size("key"));
結果:***************11
- setBit Boolean setBit(K key, long offset, boolean value);對 key 所儲存的字符串值,設置或清除指定偏移量上的位(bit)
key鍵對應的值value對應的ascii碼,在offset的位置(從左向右數)變為value
使用:template.opsForValue().set("bitTest","a");
// 'a' 的ASCII碼是 97。轉換為二進制是:01100001
// 'b' 的ASCII碼是 98 轉換為二進制是:01100010
// 'c' 的ASCII碼是 99 轉換為二進制是:01100011
//因為二進制只有0和1,在setbit中true為1,false為0,因此我要變為'b'的話第六位設置為1,第七位設置為0
template.opsForValue().setBit("bitTest",6, true);
template.opsForValue().setBit("bitTest",7, false);
System.out.println(template.opsForValue().get("bitTest"));
結果:b
- getBit Boolean getBit(K key, long offset);獲取鍵對應值的ascii碼的在offset處位值
使用:System.out.println(template.opsForValue().getBit("bitTest",7));
結果:false
作者:DreamerRzc
鏈接:https://www.jianshu.com/p/7bf5dc61ca06
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權並注明出處。
