一、 redis 特點(diǎn)
所有數(shù)據(jù)存儲(chǔ)在內(nèi)存中钧椰,高速讀寫
提供豐富多樣的數(shù)據(jù)類型:string粹断、 hash、 set嫡霞、 sorted set瓶埋、bitmap、hyperloglog
提供了 AOF 和 RDB 兩種數(shù)據(jù)的持久化保存方式诊沪,保證了 Redis 重啟后數(shù)據(jù)不丟失
Redis 的所有操作都是原子性的养筒,還支持對(duì)幾個(gè)操作合并后的原子性操作,支持事務(wù)
通常我們都把數(shù)據(jù)存到關(guān)系型數(shù)據(jù)庫(kù)中端姚,但為了提升應(yīng)用的性能晕粪,我們應(yīng)該把訪頻率高且不會(huì)經(jīng)常變動(dòng)的數(shù)據(jù)緩存到內(nèi)存中。寄锐。Redis 沒有像 MySQL 這類關(guān)系型數(shù)據(jù)庫(kù)那樣強(qiáng)大的查詢功能兵多,需要考慮如何把關(guān)系型數(shù)據(jù)庫(kù)中的數(shù)據(jù)尖啡,合理的對(duì)應(yīng)到緩存的 key-value 數(shù)據(jù)結(jié)構(gòu)中。
二剩膘、 設(shè)計(jì) Redis Key
分段設(shè)計(jì)法
使用冒號(hào)把 key 中要表達(dá)的多種含義分開表示衅斩,步驟如下:
1、把表名轉(zhuǎn)化為 key 前綴
2怠褐、主鍵名(或其他常用于搜索的字段)
3畏梆、主鍵值
4、要存儲(chǔ)的字段奈懒。
eg. 用戶表(user)
id ? ? ? ? ? ? ? ? ? ? name ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?email
1 ? ? ? ? ? ? ? ? ? ? ?zj ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 1234@163.com
2 ? ? ? ? ? ? ? ? ? ? ?ai ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 1234@163.com
這個(gè)簡(jiǎn)單的表可能經(jīng)常會(huì)有這個(gè)的需求:>根據(jù)用戶 id 查詢用戶郵箱地址奠涌,可以選擇把郵箱地址這個(gè)數(shù)據(jù)存到 redis 中:
set user:id:1:email 1234@163.com;
set user:id:2:email 1234@163.com;
三、 String數(shù)據(jù)類型的應(yīng)用場(chǎng)景
1. 簡(jiǎn)介
string 類型是 Redis 中最基本的數(shù)據(jù)類型磷杏,最常用的數(shù)據(jù)類型溜畅,甚至被很多玩家當(dāng)成 redis 唯一的數(shù)據(jù)類型去使用。string 類型在 redis 中是二進(jìn)制安全(binary safe)的,這意味著 string 值關(guān)心二進(jìn)制的字符串极祸,不關(guān)心具體格式慈格,你可以用它存儲(chǔ) json 格式或 JPEG 圖片格式的字符串。
2. 數(shù)據(jù)模型
string 類型是基本的 Key-Value 結(jié)構(gòu)遥金,Key 是某個(gè)數(shù)據(jù)在 Redis 中的唯一標(biāo)識(shí)浴捆,Value 是具體的數(shù)據(jù)。
Key ? ? ? ? ? ? ? ? ? ? ? ?Value
‘name’ ? ? ? ? ? ? ? ? ? ‘redis’
‘type’ ? ? ? ? ? ? ? ? ? ? ‘string’
3. 應(yīng)用場(chǎng)景
(1) 存儲(chǔ) MySQL 中某個(gè)字段的值
把 key 設(shè)計(jì)為 表名:主鍵名:主鍵值:字段名 eg.
set user:id:1:email 10000@qq.com
(2) 存儲(chǔ)對(duì)象
string 類型支持任何格式的字符串稿械,應(yīng)用最多的就是存儲(chǔ) json 或其他對(duì)象格式化的字符串选泻。(這種場(chǎng)景下推薦使用 hash 數(shù)據(jù)類型)
set user:id:1 '[{"id":1,"name":"zj","email":"10000@qq.com"},{"id":1,"name":"zj","email":"10000@qq.com"}]'
(3) 生成自增 id
當(dāng) redis 的 string 類型的值為整數(shù)形式時(shí),redis 可以把它當(dāng)做是整數(shù)一樣進(jìn)行自增(incr)自減(decr)操作美莫。由于 redis 所有的操作都是原子性的页眯,所以不必?fù)?dān)心多客戶端連接時(shí)可能出現(xiàn)的事務(wù)問(wèn)題。
incr 對(duì)值進(jìn)行加1操作茂嗓,如果不是整數(shù)餐茵,返回錯(cuò)誤,如果不存在按照從0開始 decr 同incr述吸,但是是減1操作 incrby,decrby 忿族,增加減去指定的數(shù)
(4) 生成自增 id
比如視頻播放次數(shù),點(diǎn)贊次數(shù)蝌矛。
(5)共享session
數(shù)據(jù)共享的功能道批,redis作為單獨(dú)的應(yīng)用軟件用來(lái)存儲(chǔ)一些共享數(shù)據(jù)供多個(gè)實(shí)例訪問(wèn)。
(6)自動(dòng)定時(shí)過(guò)期
set key value [ex seconds] [px millseconds] [nx|xx]
ex seconds: 鍵過(guò)期時(shí)間
px milliseconds: 為鍵設(shè)置毫秒級(jí)過(guò)期時(shí)間
nx: 鍵必須不存在才可以設(shè)置成功入撒,用于添加
xx: 鍵必須存在隆豹,才可以設(shè)置成功,用于更新
(7)批量操作
mset,mget
批量設(shè)置和獲取命令茅逮,在操作多個(gè)key的時(shí)候可以節(jié)省網(wǎng)絡(luò)傳輸時(shí)間
mset key value [key value...]
mget key [key ...]
四璃赡、hash 數(shù)據(jù)類型的應(yīng)用場(chǎng)景
1. 簡(jiǎn)介
hash 類型很像一個(gè)關(guān)系型數(shù)據(jù)庫(kù)的數(shù)據(jù)表判哥,hash 的 Key 是一個(gè)唯一值,Value 部分是一個(gè) hashmap 的結(jié)構(gòu)碉考。
2. 數(shù)據(jù)模型
假設(shè)有一張數(shù)據(jù)庫(kù)表如下:
id ? ? ? ? ? ? ? ?name ? ? ? ? ? ? ? type
1 ? ? ? ? ? ? ? ? redis ? ? ? ? ? ? ? ?hash
如果要用 redis 的 hash 結(jié)構(gòu)存儲(chǔ)塌计,數(shù)據(jù)模型如下:
hash數(shù)據(jù)類型在存儲(chǔ)上述類型的數(shù)據(jù)時(shí)具有比 string 類型更靈活、更快的優(yōu)勢(shì)侯谁,具體的說(shuō)锌仅,使用 string 類型存儲(chǔ),必然需要轉(zhuǎn)換和解析 json 格式的字符串墙贱,即便不需要轉(zhuǎn)換热芹,在內(nèi)存開銷方面,還是 hash 占優(yōu)勢(shì)惨撇。 和字符串很像伊脓,基本上redis對(duì)字符串操作的命令,Redis的Hash一般也存在,不過(guò)在命令前多個(gè)一個(gè)h串纺。
3. 應(yīng)用場(chǎng)景
hash 類型十分適合存儲(chǔ)對(duì)象類數(shù)據(jù)丽旅,相對(duì)于在 string 中介紹的把對(duì)象轉(zhuǎn)化為 json 字符串存儲(chǔ),hash 的結(jié)構(gòu)可以任意添加或刪除‘字段名’纺棺,更加高效靈活。 一些關(guān)系型數(shù)據(jù)庫(kù)中不是特別復(fù)雜的表邪狞,也無(wú)需復(fù)雜的關(guān)系查詢祷蝌,可以使用Redis的Hash來(lái)存儲(chǔ),也可以用Hash做表數(shù)據(jù)緩存帆卓。
hmset user:1 name zj email 123456@163.com
?
hset key field value
hsetnx key field value? //與setnx命令一樣巨朦,不存在則設(shè)置值,用于添加剑令,作用在field上面
?
hget key field //獲取值
hdel key field // 刪除值
hlen key //子酸field的個(gè)數(shù)
hmset key field value [filed value] //批量設(shè)置field-value
hexists key field? //判斷filed是否存在
hkeys key //獲取所有的field
hvals key //獲取所有的value
hgetall key //獲取所有的field-value 糊啡,如果元素?cái)?shù)較多會(huì)存在阻塞redis的可能
hincreby key filed
五、list 數(shù)據(jù)類型的應(yīng)用場(chǎng)景
1. 簡(jiǎn)介
list 是按照插入順序排序的字符串鏈表吁津,可以在頭部和尾部插入新的元素(雙向鏈表實(shí)現(xiàn)棚蓄,兩端添加元素的時(shí)間復(fù)雜度為 O(1))。插入元素時(shí)碍脏,如果 key 不存在梭依,redis 會(huì)為該 key 創(chuàng)建一個(gè)新的鏈表,如果鏈表中所有的元素都被移除典尾,該 key 也會(huì)從 redis 中移除役拴。
2. 數(shù)據(jù)模型
列表用來(lái)存儲(chǔ)多個(gè)有序的字符串,一個(gè)列表最多可以存儲(chǔ)2^32 - 1個(gè)元素钾埂,在redis中可以對(duì)列表的兩端插入push和彈出pop河闰,還可以取指定范圍的元素科平。常見操作時(shí)用 lpush 命令在 list 頭部插入元素, 用 rpop 命令在 list 尾取出數(shù)據(jù)姜性。
rpush key value [value...] //從右插入元素
lpush key value [value...] //從左邊插入元素
?
lrange key start end //獲取指定范圍的元素列表
lindex key index? //獲取列表指定索引下標(biāo)的元素
?
llen key? //獲取列表的長(zhǎng)度
?
lpop key // 從列表左側(cè)彈出元素
rpop key // 從列表右側(cè)彈出元素
lrem key count value //從列表中找到等于value的元素瞪慧,并進(jìn)行刪除,根據(jù)count的不同有不同的情況
lset key index newValue //修改指定索引下標(biāo)的元素
blpop key timeout? //阻塞式左彈出key
brpop key timeout? //阻塞式右彈出key
3. 應(yīng)用場(chǎng)景
(1) 消息隊(duì)列
redis 的 list 數(shù)據(jù)類型對(duì)于大部分使用者來(lái)說(shuō)污抬,是實(shí)現(xiàn)隊(duì)列服務(wù)的最經(jīng)濟(jì)汞贸,最簡(jiǎn)單的方式。我司使用redis做消息隊(duì)列印机,lpush + brpop或rpop命令矢腻,實(shí)現(xiàn)先進(jìn)先出,如果消費(fèi)失敗客戶端把key再放回去射赛,消費(fèi)成功就remove掉多柑。
(2) “最新內(nèi)容”
因?yàn)?list 結(jié)構(gòu)的數(shù)據(jù)查詢兩端附近的數(shù)據(jù)性能非常好,所以適合一些需要獲取最新數(shù)據(jù)的場(chǎng)景楣责,比如新聞?lì)悜?yīng)用的 “最近新聞”竣灌。
4.優(yōu)化建議
(1) list 是鏈表結(jié)構(gòu),所有如果在頭部和尾部插入數(shù)據(jù)秆麸,性能會(huì)非常高初嘹,不受鏈表長(zhǎng)度的影響;但如果在鏈表中插入數(shù)據(jù)沮趣,性能就會(huì)越來(lái)越差屯烦。
5.使用口訣:
lpush + lpop 棧 lpush + rpop 隊(duì)列 lpush + ltrim = 有限集合 lpush + brpop = 消息隊(duì)列
六、set 數(shù)據(jù)類型的應(yīng)用場(chǎng)景
1. 簡(jiǎn)介
set 數(shù)據(jù)類型是一個(gè)集合(沒有排序房铭,不重復(fù))驻龟,可以對(duì) set 類型的數(shù)據(jù)進(jìn)行添加、刪除缸匪、判斷是否存在等操作(時(shí)間復(fù)雜度是 O(1) ) set 集合不允許數(shù)據(jù)重復(fù)翁狐,如果添加的數(shù)據(jù)在 set 中已經(jīng)存在,將只保留一份凌蔬。 set 類型提供了多個(gè) set 之間的聚合運(yùn)算露懒,如求交、并龟梦、差集隐锭,這些操作在 redis 內(nèi)部完成,效率很高计贰。
2. 數(shù)據(jù)模型
sadd key value [value...] //添加元素
srem key value [value...] //刪除元素
scard key ? //計(jì)算元素的個(gè)數(shù)
sismember key value //判斷元素是否在集合中
srandmember key [count]? //隨機(jī)從集合中返回指定個(gè)數(shù)的元素钦睡,不寫默認(rèn)為1
spop key //從集合隨機(jī)取出元素
smembers key //獲取集合內(nèi)的所有元素
?
sinter key1 key2 //求集合的交集
sunion key1 key2 //求集合的并集
sdiff key1 key2? //求集合的差集
3. 應(yīng)用場(chǎng)景
set 類型的特點(diǎn)是——不重復(fù)且無(wú)序的一組數(shù)據(jù),并且具有豐富的計(jì)算功能躁倒,在一些特定的場(chǎng)景中可以高效的解決一般關(guān)系型數(shù)據(jù)庫(kù)不方便做的工作荞怒。
(1)“共同好友列表”
社交類應(yīng)用中洒琢,獲取兩個(gè)人或多個(gè)人的共同好友,兩個(gè)人或多個(gè)人共同關(guān)注的微博這樣類似的功能褐桌,用 MySQL 的話操作很復(fù)雜衰抑,可以把每個(gè)人的好友 id 存到集合中,獲取共同好友的操作就可以簡(jiǎn)單到一個(gè)取交集的命令就搞定荧嵌。
// 這里為了方便閱讀呛踊,把 id 替換成姓名
sadd user:wade james melo paul kobe
sadd user:james wade melo paul kobe
sadd user:paul wade james melo kobe
sadd user:melo wade james paul kobe
?
// 獲取 wade 和 james 的共同好友
sinter user:wade user:james
/* 輸出:
* ? ? ?1) "kobe"
* ? ? ?2) "paul"
* ? ? ?3) "melo"
*/
// 獲取香蕉四兄弟的共同好友
sinter user:wade user:james user:paul user:melo
/* 輸出:
* ? ? ?1) "kobe"
*/
/*
? ? 類似的需求還有很多 , 必須把每個(gè)標(biāo)簽下的文章 id 存到集合中,可以很容易的求出幾個(gè)不同標(biāo)簽下的共同文章啦撮;
把每個(gè)人的愛好存到集合中谭网,可以很容易的求出幾個(gè)人的共同愛好。
*/
(2)唯一ip
跟蹤一些具有唯一性的一些數(shù)據(jù)赃春,比如訪問(wèn)某一博客的唯一ip地址的信息愉择,我們僅需要在每次訪問(wèn)的時(shí)候,將ip存入redis中织中。利用服務(wù)器端聚合操作方便高效的特性锥涕,維護(hù)數(shù)據(jù)對(duì)象之間的關(guān)聯(lián)關(guān)系。
七狭吼、sorted set 數(shù)據(jù)類型的應(yīng)用場(chǎng)景
1.簡(jiǎn)介
在 set 的基礎(chǔ)上給集合中每個(gè)元素關(guān)聯(lián)了一個(gè)分?jǐn)?shù)层坠,往有序集合中插入數(shù)據(jù)時(shí)會(huì)自動(dòng)根據(jù)這個(gè)分?jǐn)?shù)排序。它保留了元素不能重復(fù)的特性刁笙,并且元素是有序的窿春。
2.基本操作
zadd key score member? //score是可以重復(fù)的,添加key的時(shí)候指定分?jǐn)?shù)
zcard key //計(jì)算成員個(gè)數(shù)
zscore key member //計(jì)算某個(gè)成員的分?jǐn)?shù)
zrank key member //計(jì)算成員排名采盒,從低到高
zrevrank key member //計(jì)算成員排名,從高到低
zrem key member [member...]? //刪除成員
zincrby key increnment member //增加成員的分?jǐn)?shù)
zrange key start end [withscores]? //從低到高返回指定排名的分?jǐn)?shù)
zrevrange key start end [withscores]? //從高到低返回
?
zrangebyscore key min max [withscores] [limit offset count] //按照分?jǐn)?shù)從低到高返回
zrevrange score? key min max [withscores] [limit offset count] //按照分?jǐn)?shù)從高到低返回成員
?
withscore 代表返回的時(shí)候帶上成員的分?jǐn)?shù)
?
...還有求交集蔚润,并集等操作
3.應(yīng)用場(chǎng)景
在集合類型的場(chǎng)景上加入排序就是有序集合的應(yīng)用場(chǎng)景了磅氨。
(1)根據(jù)好友的“親密度”排序顯示好友列表。
// 用元素的分?jǐn)?shù)(score)表示與好友的親密度
zadd user:kobe 80 james 90 wade ?85 melo ?90 paul
?
// 根據(jù)“親密度”給好友排序
zrevrange user:kobe 0 -1
?
/**
* 輸出:
* ? ? ?1) "wade"
* ? ? ?2) "paul"
* ? ? ?3) "melo"
* ? ? ?4) "james"
*/
// 增加好友的親密度
zincrby user:kobe 15 james
?
// 再次根據(jù)“親密度”給好友排序
zrevrange user:kobe 0 -1
?
/**
* 輸出:
* ? ? ?1) "james"
* ? ? ?2) "wade"
* ? ? ?3) "paul"
* ? ? ?2) "melo"
*/
//類似的需求還出現(xiàn)在根據(jù)文章的閱讀量或點(diǎn)贊量對(duì)文章列表排序
(2)排行榜
實(shí)效性
從排行榜的實(shí)效性上劃分嫡纠,主要分為:
實(shí)時(shí)榜:基于當(dāng)前一段時(shí)間內(nèi)數(shù)據(jù)的實(shí)時(shí)更新烦租,進(jìn)行排行。例如:當(dāng)前一小時(shí)內(nèi)游戲熱度實(shí)時(shí)榜除盏,當(dāng)前一小時(shí)內(nèi)明星送花實(shí)時(shí)榜等
歷史榜:基于歷史一段周期內(nèi)的數(shù)據(jù)叉橱,進(jìn)行排行。例如:日榜(今天看昨天的)者蠕,周榜(上一周的)窃祝,月榜(上個(gè)月的),年榜(上一年的)
業(yè)務(wù)數(shù)據(jù)類型
從需要排行的數(shù)據(jù)類型上劃分踱侣,主要分為:
單類型數(shù)據(jù)排行榜:是指需要排行的主體不需要區(qū)分類型粪小,例如大磺,所有用戶積分排行,所有公貢獻(xiàn)值排行探膊,所有游戲熱度排行等
多類型(復(fù)合類型)數(shù)據(jù)排行榜:是指需要排行的主體在排行中要求有類型上的區(qū)分杠愧,例如:競(jìng)技類游戲熱度排行、體育類游戲熱度排行逞壁、MOBA類游戲操作性排行流济、角色/回合/卡牌三類游戲熱度排行等
展示唯度
從榜單的最終展示唯度上劃分,主要分為:
單唯度:是指選擇展示的排行榜就是基于一個(gè)唯度下的排行腌闯,例如前面提到的MOBA類游戲操作性排行榜绳瘟,就僅展示所有MOBA類游戲按操作性的評(píng)分排行
多唯度:是指選擇展示的排行榜還有多種唯度供用戶選擇,仍然以前面的MOBA類游戲?yàn)槔筻冢ǘ瘸瞬僮餍曰€有音效評(píng)分排行,難易度評(píng)分排行工腋,畫面評(píng)分排行等姨丈。
展示數(shù)據(jù)量
從需要展示的數(shù)據(jù)量上劃分,主要分為:
topN數(shù)據(jù):只要求展示topN條排行紀(jì)錄擅腰,例如:最火MOBA游戲top20
全量數(shù)據(jù):要求展示所有數(shù)據(jù)的排行蟋恬,例如:所有用戶的積分排行
八.項(xiàng)目中哪些地方用到了Redis
數(shù)據(jù)采集字典表基礎(chǔ)數(shù)據(jù)
最新數(shù)據(jù)采集值
物聯(lián)網(wǎng)設(shè)備傳送byte[]緩存
環(huán)境閾值
讀者福利:
Java高級(jí)資料需要自己領(lǐng)取,涵蓋了Java趁冈、Redis歼争、MongoDB、MySQL渗勘、Zookeeper沐绒、Spring boot、Dubbo高并發(fā)分布式等教程旺坠。
點(diǎn)擊了解更多乔遮,獲取更多Java高級(jí)進(jìn)階資料!取刃!