目錄String簡單介紹常見命令應用場景Hash簡單介紹常見命令應用場景List簡單介紹常見命令應用場景Set簡單介紹常見命令應用場景Sorted Set(Zset)簡單介紹常見命令應用場景Bitmap簡單介紹常見命令應用場景附錄 Redis支持多種數據類型,比如String、hash、list、S ...
目錄
Redis支持多種數據類型,比如String、hash、list、Set、SortedSet、Streams、Bitmap、Hyperloglog、Geo(物理位置)等等,在官網也給出了說明,本博客就挑一些比較常有的數據類型說說,本文例子基於Redisson實現
String
簡單介紹
在Redis中,所有的數據都是key-value
的數據結構存儲的,那麼在Redis中這個string類型的value值只能存儲String類型的數據?其實不然,redis中string類型的value值是可以支持多種類型的,比如String、Number、Float、Bits等等,但是最大還是只能存儲512M。Redis中key也是string類型存儲的,所以最大也只能存儲512M
常見命令
set
、get
命令就不演示了,下麵給出一些常有命令
批量設置多個key
mset tkey1 tvalue tkey2 111
批量獲取多個key值
mget tkey1 tkey2
獲取長度
strlen tkey
字元串後面追加內容
append tkey tstring
獲取指定範圍的字元
# 取0~3之間的字元,返回1tst
getrange tkey 0 3
key進行遞增(整數)
# 返回1
incr ikey
# 遞增指定大小的值,返回124
incrby ikey 124
key進行遞增(浮點數)
# 設置初始浮點數值
set fkey 1.2
# 在原來基礎上遞增2.4,返回3.6
incryfloat fkey 2.4
加上key過期時間
expire tkey 10
分散式鎖實現,set if not exists,可以使用setnx單個命令,也可以使用set結合nx命令來實現
# set tkey過期時間10秒,nx:如果鍵不存在時設置
set tkey aaa ex 10 nx
# setnx命令,相當於set和nx命令一起用
setnx tkey aaa
EX : 設置指定的到期時間(以秒為單位)。
PX : 設置指定的到期時間(以毫秒為單
NX : 僅在鍵不存在時設置鍵。
XX : 只有在鍵已存在時才設置。
String 更多指令請參考官網文檔:https://redis.io/commands/?group=string
應用場景
對於Redis String類型的應用場景也比較多,比如很常有的做緩存處理,也可以用於分散式鎖、分散式ID
分散式鎖的實現主要依賴於命令
setnx
分散式ID主要是利用
incr
這個命令
基於Redis實現一個分散式ID生成器
package com.example.redis.common.handlers;
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* <pre>
* Redis分散式ID生成器
* </pre>
*
* <pre>
* 修改記錄
* 修改後版本: 修改人: 修改日期: 2023/11/07 14:18 修改內容:
* </pre>
*/
@Component
public class RedisIdentifierGenerator implements IdentifierGenerator {
@Resource
private RedisTemplate redisTemplate;
@Override
public Number nextId(Object entity) {
String key = entity.getClass().getName();
return redisTemplate.opsForValue().increment(key);
}
}
Hash
簡單介紹
Hash哈希,數據類型也是一種比較常見的數據結構,相對於Redis的string類型而言,其實就是多了一層key(field),所以說只要string類型適用的場景,hash都是支持的
常見命令
hash設置key為hkey,field為a的值
hset hkey a aaaa
獲取hkey的field值
hget hkey a
設置多個field值
hmset hkey a 1 b 2 c 3 d 4
獲取多個field值
hmget hkey a b c d
獲取key所有的field
hkeys hkey
獲取key所有field的值
hvals hkey
獲取key所有fileld和值
hgetall hkey
給key某個欄位field添加值
hincrby hkey a 10
對於Hash的更多命令,請參考:https://redis.io/commands/?group=hash
應用場景
對於hash的應用場景,其實只要redis string類型適用的,hash都是適用的,不過hash這種特殊的數據結構,還是適用於一些特殊場景的
- 存儲一個對象類的數據,這個對象的多個欄位就對應hash的field
- 存儲一些統計類的數據,比如訪問量、點擊量等等
如圖,如果要統計博客的pv、uv還有評論數量(evaluation_count),隨著博客數量的增加存儲到資料庫里,後面肯定會查詢比較慢,所以可以使用redis進行緩存
使用Redisson來寫一個例子:
@Resource
private RedissonClient redissonClient;
@Test
void contextLoads() throws ExecutionException, InterruptedException {
RMap<Object, Object> redissonClientMap = redissonClient.getMap("recordMap");
Map<String,Integer> map = new HashMap<>();
map.put("pv" , 1000);
map.put("uv" , 1500);
map.put("evaluation_count",30)
redissonClientMap.putAll(map);
System.out.println(redissonClientMap.addAndGet("pv", 2));
}
List
簡單介紹
redis中的數據類型存儲有序的字元串列表,元素是可以重覆,列表的最大長度為2^32-1
個元素(4294967295),即每個列表超過40億個元素
常見命令
左右添加元素
# 左邊添加元素
lpush queueList a
lpush queueList b c
# 右邊添加元素
rpush queueList d e
左右彈出第一條
# 左邊彈出一個元素
lpop queueList
# 右邊彈出一個元素
rpop queueList
左右彈出一個元素,並且設置超時,直到無數據彈出或者超時
blpop queueList 10
brpop queueList 10
應用場景
-
微信公眾號、微博等消息流列表
RDeque<Object> recordList = redissonClient.getDeque("recordList"); recordList.addFirst("1.新聞1"); recordList.addFirst("2.新聞2"); recordList.addFirst("3.新聞3"); IntStream.range(0,3).forEach(a->{ System.out.println(recordList.poll()); });
-
消息隊列,使用redis也可以實現消息隊列,比如使用
rpush/lpop
實現簡單隊列;blpop
或者是brpop
來實現阻塞讀取隊列;補充說明,同時stream
、pub/sub
(訂閱發佈模式)、sortedSet
等等也是可以實現的不過還是不建議使用Redis來實現消息隊列,因為我們已經有成熟的MQ框架,使用redis實現隊列有可能有下麵的問題:
- 存在記憶體,可能會有數據丟失,不能重覆消費
- 消費後不能回應,沒有ack確認機制
Set
簡單介紹
Redis中的Set類型是無序集合,最大存儲數量為2^32-1
,大概有40億左右,添加、刪除元素的時間複雜度都是O(1)
常見命令
添加一個或者多個元素
sadd skey a b c d e f g h
獲取所有的元素
smembers skey
獲取集合元素的個數
scard skey
隨機獲取一個元素
srandmember skey
隨機彈出一個元素
spop skey
彈出指定的元素
# 如果兩個元素都有,返回2
srem skey a g
檢查元素是否存在
# 元素存在返回1
sismember skey e
獲取前一個集合有,而後面一個集合沒有的元素
sdiff skey skey1
獲取集合的交集
sinter skey skey1
獲取集合的並集
sunion skey skey1
Set的更多命令請參考:https://redis.io/commands/?group=set
應用場景
-
抽獎程式,利用
spop
跟standmember
隨機彈出元素RSet<String> recordSet = redissonClient.getSet("recordSet"); List<String> members = Lists.newArrayList("alice", "tim","tom" , "風清揚", "jack" ); recordSet.addAll(members); RFuture<Set<String>> threeSet = recordSet.removeRandomAsync(3 ); RFuture<Set<String>> twoSet = recordSet.removeRandomAsync(2 ); RFuture<Set<String>> oneSet = recordSet.removeRandomAsync(1 ); System.out.println("三等獎:"+threeSet.get()); System.out.println("二等獎:"+twoSet.get()); System.out.println("一等獎:"+oneSet.get());
-
集合交集(sinter)、並集(sunion)的場景,可以實現共同關註等場景
RSet<Object> tom = redissonClient.getSet("tom"); tom.addAll(Lists.newArrayList("令狐沖","james","風清揚")); RSet<Object> jack = redissonClient.getSet("jack"); jack.addAll(Lists.newArrayList("令狐沖","tim","jack")); System.out.println("共同關註的人:"+tom.readIntersectionAsync("jack").get());
-
sadd 集合存儲,實現點贊、簽到的業務場景
Sorted Set(Zset)
簡單介紹
相對於set來說,sorted set是一種有序的set,排序是根據每個元素的score排序的,score相同時根據key的ASCII碼排序
常見命令
批量添加元素
zadd z1 10 a 20 b 30 c 40 d 50 e 60 f 70 g 80 h 90 i
根據分數從低到高
zrange z1 0 -1 withscore
根據分數從高到低
zrevrange z1 0 -1 withscores
根據分數範圍取值
zrangebyscore z1 20 30
移除元素
zrem z1 i
獲取有序集合個數
zcard z1
給某個元素加分值
zincrby z1 20 a
獲取範圍內的個數
zcount z1 50 60
返回指定元素的索引值
# 假如d元素排在第4位,索引值就返回3
zrank z1 d
獲取元素的分數
zscore z1 h
Sorted Set的更多命令請參考:https://redis.io/commands/?group=sorted_set
應用場景
-
排行榜
RScoredSortedSet<String> school = redissonClient.getScoredSortedSet("school"); school.add(60, "tom"); school.add(60, "jack"); school.add(60, "tim"); school.addScore("tom", 20); school.addScore("jack", 10); school.addScore("tim", 30); RFuture<Collection<ScoredEntry<String>>> collectionRFuture = school.entryRangeReversedAsync(0, -1); Iterator<ScoredEntry<String>> iterator = collectionRFuture.get().iterator(); System.out.println("成績從高到低排序"); while(iterator.hasNext()) { ScoredEntry<String> next = iterator.next(); String value = next.getValue(); System.out.println(value); } RFuture<Collection<ScoredEntry<String>>> collectionRFuture1 = school.entryRangeReversedAsync(0, 2); Iterator<ScoredEntry<String>> iterator1 = collectionRFuture1.get().iterator(); System.out.println("成績前三名"); while (iterator1.hasNext()) { System.out.println(iterator1.next().getValue()); }
Bitmap
簡單介紹
點陣圖不是實際的數據類型,而是String類型中定義的一種面向位的操作,所以這個點陣圖的最大存儲量也是512M。可以容納最少2^32不同的位,可以在不同的位置設置0或者1
常見命令
設置位的值
# 將位2設置為1
setbit permit 2 1
獲取位的值
getbit permit 2
獲取key的為1的個數
# 獲取位為1的總數
bitcount permit
獲取0或者1的第一位
# 獲取key permit 位為1的第一個位置
bitpos permit 1
獲取多個bitmap的位操作,比如&
、|
# 獲取bkey和permit這兩個的&運算,並且賦值給hbit
bitop AND hbit bkey permit
應用場景
-
實時的數據統計
比如:人員的考勤打卡記錄,例如學生tom每次來上課就將相關的位記錄位1
假如當月的第一天、第五天、第十天都來了
setbit tom 1 1
setbit tom 5 1
setbit tom 10 1
如何每月考勤,統計一下這個用戶當月來了幾天
bitcount tom
也可以應用於統計一個網站一天有多少用戶訪問,例如用戶ID為123、124、125的用戶訪問了csdn
setbit csdn:2023-11-08 123 1
setbit csdn:2023-11-08 124 1
setbit csdn:2023-11-08 125 1
...
# 統計一下當天的訪問次數
bitcount csdn:2023-11-08
- 存儲用戶許可權,比如用1來表示有許可權,0表示沒許可權,使用點陣圖可以節省很大的存儲空間
附錄
Redis命令查詢網站:https://redis.io/commands/