Redis 16 個常見使用場景
這個場景最開始是是一篇介紹微博Redis應用的PPT中看到的,其中提到微博的Redis主要是用在在計數和好友關系兩方面上,當時對好友關系方面的用法不太了解,后來看到《Redis設計與實作》中介紹到作者最開始去使用Redis便是希望能通過,利用set結構的無序性,通過Spop(RedisSpop命令用于移除集合中的指定key的一個或多個隨機元素,移除后會回傳移除的元素,在Redis的資料結構中,在最
1. 快取
作為Key-Value形態的記憶體資料庫,Redis 最先會被想到的應用場景便是作為資料快取,而使用 Redis 快取資料非常簡單,只需要通過string型別將序列化后的物件存起來即可,不過也有一些需要注意的地方:
-
必須保證不同物件的 key 不會重復,并且使 key 盡量短,一般使用類名(表名)加主鍵拼接而成,
-
選擇一個優秀的序列化方式也很重要,目的是提高序列化的效率和減少記憶體占用,
-
快取內容與資料庫的一致性,這里一般有兩種做法:
- 只在資料庫查詢后將物件放入快取,如果物件發生了修改或洗掉操作,直接清除對應快取(或設為過期),
- 在資料庫新增和查詢后將物件放入快取,修改后更新快取,洗掉后清除對應快取(或設為過期),
2. 資料共享分布式
String 型別,因為 Redis 是分布式的獨立服務,可以在多個應用之間共享
例如:分布式Session
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
3、分布式鎖
如今都是分布式的環境下java自帶的單體鎖已經不適用的,在 Redis 2.6.12 版本開始,string的set命令增加了一些引數:
-
EX:設定鍵的過期時間(單位為秒) -
PX:設定鍵的過期時間(單位為毫秒) -
NX:只在鍵不存在時,才對鍵進行設定操作,SET key value NX效果等同于SETNX key value, -
XX:只在鍵已經存在時,才對鍵進行設定操作,
由于這個操作是原子性的,可以簡單地以此實作一個分布式的鎖,例如:
set lock_key locked NX EX 1
如果這個操作回傳false,說明 key 的添加不成功,也就是當前有人在占用這把鎖,而如果回傳true,則說明得了鎖,便可以繼續進行操作,并且在操作后通過del命令釋放掉鎖,并且即使程式因為某些原因并沒有釋放鎖,由于設定了過期時間,該鎖也會在 1 秒后自動釋放,不會影響到其他程式的運行,
推薦使用 redisson 第三方庫實作分布式鎖,
參考 java分布式鎖終極解決方案之 redisson
4、全域ID
int型別,incrby,利用原子性
incrby userid 1000
分庫分表的場景,一次性拿一段
5、計數器
int型別,incr方法
例如:文章的閱讀量、微博點贊數、允許一定的延遲,先寫入Redis再定時同步到資料庫
計數功能應該是最適合 Redis 的使用場景之一了,因為它高頻率讀寫的特征可以完全發揮 Redis 作為記憶體資料庫的高效,在 Redis 的資料結構中,string、hash和sorted set都提供了incr方法用于原子性的自增操作,下面舉例說明一下它們各自的使用場景:
- 如果應用需要顯示每天的注冊用戶數,便可以使用
string作為計數器,設定一個名為REGISTERED_COUNT_TODAY的 key,并在初始化時給它設定一個到凌晨 0 點的過期時間,每當用戶注冊成功后便使用incr命令使該 key 增長 1,同時當每天凌晨 0 點后,這個計數器都會因為 key 過期使值清零, - 每條微博都有點贊數、評論數、轉發數和瀏覽數四條屬性,這時用
hash進行計數會更好,將該計數器的 key 設為weibo:weibo_id,hash的 field 為like_number、comment_number、forward_number和view_number,在對應操作后通過hincrby使hash 中的 field 自增, - 如果應用有一個發帖排行榜的功能,便選擇
sorted set吧,將集合的 key 設為POST_RANK,當用戶發帖后,使用zincrby將該用戶 id 的 score 增長 1,sorted set會重新進行排序,用戶所在排行榜的位置也就會得到實時的更新,
6、限流
int型別,incr方法
以訪問者的ip和其他資訊作為key,訪問一次增加一次計數,超過次數則回傳false
7、位統計
String型別的bitcount(1.6.6的bitmap資料結構介紹)
字符是以8位二進制存盤的
set k1 a
setbit k1 6 1
setbit k1 7 0
get k1
/* 6 7 代表的a的二進制位的修改
a 對應的ASCII碼是97,轉換為二進制資料是01100001
b 對應的ASCII碼是98,轉換為二進制資料是01100010
因為bit非常節省空間(1 MB=8388608 bit),可以用來做大資料量的統計,
*/
參考 使用Redis的bitmaps統計用戶留存率、活躍用戶
用戶榷訓月活怎么統計 - Redis HyperLogLog 詳解
8. 時間軸(Timeline)
list作為雙向鏈表,不光可以作為佇列使用,如果將它用作堆疊便可以成為一個公用的時間軸,當用戶發完微博后,都通過lpush將它存放在一個 key 為LATEST_WEIBO的list中,之后便可以通過lrange取出當前最新的微博,
9. 訊息佇列
Redis 中list的資料結構實作是雙向鏈表,所以可以非常便捷的應用于訊息佇列(生產者 / 消費者模型),訊息的生產者只需要通過lpush將訊息放入 list,消費者便可以通過rpop取出該訊息,并且可以保證訊息的有序性,如果需要實作帶有優先級的訊息佇列也可以選擇sorted set,而pub/sub功能也可以用作發布者 / 訂閱者模型的訊息,無論使用何種方式,由于 Redis 擁有持久化功能,也不需要擔心由于服務器故障導致訊息丟失的情況,
List提供了兩個阻塞的彈出操作:blpop/brpop,可以設定超時時間
- blpop:blpop key1 timeout 移除并獲取串列的第一個元素,如果串列沒有元素會阻塞串列直到等待超時或發現可彈出元素為止,
- brpop:brpop key1 timeout 移除并獲取串列的最后一個元素,如果串列沒有元素會阻塞串列直到等待超時或發現可彈出元素為止,
上面的操作,其實就是java的阻塞佇列,學習的東西越多,學習成本越低
- 佇列:先進先除:rpush blpop,左頭右尾,右邊進入佇列,左邊出佇列
- 堆疊:先進后出:rpush brpop
10、抽獎
利用set結構的無序性,通過 Spop( Redis Spop 命令用于移除集合中的指定 key 的一個或多個隨機元素,移除后會回傳移除的元素, ) 隨機獲得值
redis> SADD myset "one"
(integer) 1
redis> SADD myset "two"
(integer) 1
redis> SADD myset "three"
(integer) 1
redis> SPOP myset
"one"
redis> SMEMBERS myset
1) "three"
2) "two"
redis> SADD myset "four"
(integer) 1
redis> SADD myset "five"
(integer) 1
redis> SPOP myset 3
1) "five"
2) "four"
3) "two"
redis> SMEMBERS myset
1) "three"
redis>
11、點贊、簽到、打卡

假如上面的微博ID是t1001,用戶ID是u3001
用 like:t1001 來維護 t1001 這條微博的所有點贊用戶
- 點贊了這條微博:sadd like:t1001 u3001
- 取消點贊:srem like:t1001 u3001
- 是否點贊:sismember like:t1001 u3001
- 點贊的所有用戶:smembers like:t1001
- 點贊數:scard like:t1001
是不是比資料庫簡單多了,
12 商品標簽

老規矩,用 tags:i5001 來維護商品所有的標簽,
- sadd tags:i5001 畫面清晰細膩
- sadd tags:i5001 真彩清晰顯示屏
- sadd tags:i5001 流程至極
13、好友關系、用戶關注、推薦模型
這個場景最開始是是一篇介紹微博 Redis 應用的 PPT 中看到的,其中提到微博的 Redis 主要是用在在計數和好友關系兩方面上,當時對好友關系方面的用法不太了解,后來看到《Redis 設計與實作》中介紹到作者最開始去使用 Redis 便是希望能通過set解決傳統資料庫無法快速計算集合中交集這個功能,后來聯想到微博當前的業務場景,確實能夠以這種方式實作,所以姑且猜測一下:
對于一個用戶 A,將它的關注和粉絲的用戶 id 都存放在兩個 set 中:
-
A:follow:存放 A 所有關注的用戶 id -
A:follower:存放 A 所有粉絲的用戶 id那么通過
sinter命令便可以根據A:follow和A:follower的交集得到與 A 互相關注的用戶,當 A 進入另一個用戶 B 的主頁后,A:follow和B:follow的交集便是 A 和 B 的共同專注,A:follow和B:follower的交集便是 A 關注的人也關注了 B,
舉例
follow 關注 fans 粉絲
相互關注:
- sadd 1:follow 2
- sadd 2:fans 1
- sadd 1:fans 2
- sadd 2:follow 1
我關注的人也關注了他(取交集):
- sinter 1:follow 2:fans
可能認識的人:
- 用戶1可能認識的人(差集):sdiff 2:follow 1:follow
- 用戶2可能認識的人:sdiff 1:follow 2:follow
14 .排行榜
使用sorted set(有序set)和一個計算熱度的演算法便可以輕松打造一個熱度排行榜,zrevrangebyscore可以得到以分數倒序排列的序列,zrank可以得到一個成員在該排行榜的位置(是分數正序排列時的位置,如果要獲取倒序排列時的位置需要用zcard-zrank),
id 為6001 的新聞點擊數加1:
zincrby hotNews:20190926 1 n6001
獲取今天點擊最多的15條:
zrevrange hotNews:20190926 0 15 withscores
15 .倒排索引
倒排索引是構造搜索功能的最常見方式,在 Redis 中也可以通過set進行建立倒排索引,這里以簡單的拼音 + 前綴搜索城市功能舉例:
假設一個城市北京,通過拼音詞庫將北京轉為beijing,再通過前綴分詞將這兩個詞分為若干個前綴索引,有:北、北京、b、be…beijin和beijing,將這些索引分別作為set的 key(例如:index:北)并存盤北京的 id,倒排索引便建立好了,接下來只需要在搜索時通過關鍵詞取出對應的set并得到其中的 id 即可,
16 .顯示最新的專案串列
比如說,我們的一個Web應用想要列出用戶貼出的最新20條評論,在最新的評論邊上我們有一個“顯示全部”的鏈接,點擊后就可以獲得更多的評論,
每次新評論發表時,我們會將它的ID添加到一個Redis串列,可以限定串列的長度為5000
LPUSH latest.comments
在Redis中我們的最新ID使用了常駐快取,這是一直更新的,但是我們做了限制不能超過5000個ID,因此我們的獲取ID函式會一直詢問Redis,只有在超出了這個范圍的時候,才需要去訪問資料庫,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/543166.html
標籤:Java
