面試官:Redis五種基本數(shù)據(jù)類型的應(yīng)用場(chǎng)景是啥?
string
緩存
簡(jiǎn)單key-value存儲(chǔ)
分布式鎖
setnx key value,當(dāng)key不存在時(shí),將 key 的值設(shè)為 value ,返回1
若給定的 key 已經(jīng)存在,則setnx不做任何動(dòng)作,返回0。
當(dāng)setnx返回1時(shí),表示獲取鎖,做完操作以后del key,表示釋放鎖,如果setnx返回0表示獲取鎖失敗,整體思路大概就是這樣
計(jì)數(shù)器
如知乎每個(gè)問題的被瀏覽器次數(shù)

- set key 0
- incr key // incr readcount::{帖子id} 每閱讀一次
- get key // get readcount::{帖子id} 獲取閱讀量
分布式全局唯一id
分布式全局唯一id的實(shí)現(xiàn)方式有很多,這里只介紹用redis實(shí)現(xiàn)

每次獲取userId的時(shí)候,對(duì)userId加1再獲取,可以改進(jìn)為如下形式

直接獲取一段userId的最大值,緩存到本地慢慢累加,快到了userId的最大值時(shí),再去獲取一段,一個(gè)用戶服務(wù)宕機(jī)了,也頂多一小段userId沒有用到
- set userId 0
- incr usrId //返回1
- incrby userId 1000 //返回10001
hash
redis的散列可以讓用戶將多個(gè)鍵值對(duì)存儲(chǔ)到一個(gè)Redis的鍵里面,散列非常適用于將一些相關(guān)的數(shù)據(jù)存儲(chǔ)在一起。類似map的一種結(jié)構(gòu),將結(jié)構(gòu)化的數(shù)據(jù),比如一個(gè)對(duì)象(前提是這個(gè)對(duì)象沒嵌套其他的對(duì)象)給緩存到redis中,以后每次讀寫內(nèi)存時(shí),就可以操作hash里的某個(gè)字段
list
消息隊(duì)列

在list里面一邊進(jìn),一邊出即可
- ## 實(shí)現(xiàn)方式一
- lpush key value //一直往list左邊放
- brpop key value 10
- //key這個(gè)list有元素時(shí),直接彈出,沒有元素被阻塞,直到等待超時(shí)或發(fā)現(xiàn)可彈出元素為止,上面例子超時(shí)時(shí)間為10s
- ## 實(shí)現(xiàn)方式二
- rpush key value
- blpop key value 10
新浪/Twitter用戶消息列表

加入說小編li關(guān)注了2個(gè)微博a和b,a發(fā)了一條微博(編號(hào)為100)就執(zhí)行如下命令
- lpush msg::li 100
b發(fā)了一條微博(編號(hào)為200)就執(zhí)行如下命令:
- lpush msg::li 200
假如想拿最近的10條消息就可以執(zhí)行如下命令(最新的消息一定在list的最左邊):
- lrange msg::li 0 9 //下標(biāo)從0開始,[start,stop]是閉區(qū)間,都包含
set
無序集合,自動(dòng)去重,將數(shù)據(jù)放到set中就可去重,可以基于JVM的HashSet去重,如果系統(tǒng)部署在多臺(tái)機(jī)器上,就可以用redis進(jìn)行全局去重
可以基于set做交集,并集,差集的操作。如把2個(gè)人的粉絲列表弄一個(gè)交集,就能看到兩個(gè)人的共同好友是誰
實(shí)現(xiàn)點(diǎn)贊,簽到,like等功能

- // 1001用戶給8001帖子點(diǎn)贊
- sadd like::8001 1001
- srem like::8001 1001 //取消點(diǎn)贊
- sismember like::8001 1001 //檢查用戶是否點(diǎn)過贊
- smembers like::8001 //獲取點(diǎn)贊的用戶列表
- scard like::8001 //獲取點(diǎn)贊用戶數(shù)
實(shí)現(xiàn)關(guān)注模型,可能認(rèn)識(shí)的人

seven關(guān)注的人
sevenSub -> {qing, mic, james}
青山關(guān)注的人
qingSub->{seven,jack,mic,james}
Mic關(guān)注的人
MicSub->{seven,james,qing,jack,tom}
- //返回sevenSub和qingSub的交集,即seven和青山的共同關(guān)注
- sinter sevenSub qingSub -> {mic,james}
- // 我關(guān)注的人也關(guān)注他,下面例子中我是seven
- // qing在micSub中返回1,否則返回0
- sismember micSub qing
- sismember jamesSub qing
- // 我可能認(rèn)識(shí)的人,下面例子中我是seven
- // 求qingSub和sevenSub的差集,并存在sevenMayKnow集合中
- sdiffstore sevenMayKnow qingSub sevenSub -> {seven,jack}
電商商品篩選

每個(gè)商品入庫(kù)的時(shí)候即會(huì)建立他的靜態(tài)標(biāo)簽列表如,品牌,尺寸,處理器,內(nèi)存
- // 將拯救者y700P-001和ThinkPad-T480這兩個(gè)元素放到集合brand::lenovo
- sadd brand::lenovo 拯救者y700P-001 ThinkPad-T480
- sadd screenSize::15.6 拯救者y700P-001 機(jī)械革命Z2AIR
- sadd processor::i7 拯救者y700P-001 機(jī)械革命X8TIPlus
- // 獲取品牌為聯(lián)想,屏幕尺寸為15.6,并且處理器為i7的電腦品牌(sinter為獲取集合的交集)
- sinter brand::lenovo screenSize::15.6 processor::i7 -> 拯救者y700P-001
zset
排序的set,可以去重還可以排序,寫進(jìn)去的時(shí)候給一個(gè)分?jǐn)?shù),自動(dòng)根據(jù)根據(jù)分?jǐn)?shù)排序,分?jǐn)?shù)可以自定義排序規(guī)則
redis的zset天生是用來做排行榜的、好友列表, 去重, 歷史記錄等業(yè)務(wù)需求

- // user1的用戶分?jǐn)?shù)為 10
- zadd ranking 10 user1
- zadd ranking 20 user2
- // 取分?jǐn)?shù)最高的3個(gè)用戶
- zrevrange ranking 0 2 withscores