01_redis_基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)

安裝

  1. Docker
docker pull redis
docker run --name myredis -d -p6379:6379 redis
docker exec -it myredis redis-cli
  1. 直接安裝
 brew install redis 
# ubuntu 
 apt-get install redis 
# redhat
 yum install redis 
# 運行客戶端
 redis-cli
  1. 源碼啟動
    windows版:
    https://github.com/MSOpenTech/redis/releases
    解壓:Redis-x64-3.2.100.zip
    在解壓目錄下
啟動服務(wù)
redis-server.exe 
啟動客戶端,連接服務(wù)器
redis-cli.exe 
安裝為windows服務(wù)
redis-server.exe --service-install redis.windows.conf 
卸載服務(wù):
redis-server --service-uninstall
開啟服務(wù):
redis-server --service-start
停止服務(wù):
redis-server --service-stop
重命名服務(wù):
redis-server --service-name name

應(yīng)用場景

  1. 記錄帖子點贊數(shù),評論數(shù),點擊數(shù)
  2. 緩存用戶行為歷史
  3. 有關(guān)id

數(shù)據(jù)結(jié)構(gòu)

五種數(shù)據(jù)結(jié)構(gòu)

  1. string
  2. list
  3. set
  4. hash
  5. zset

1. 字符串string

string 是redis最簡單的數(shù)據(jù)結(jié)構(gòu)界睁,所有數(shù)據(jù)結(jié)構(gòu)的key都是以唯一的string作為名稱,然后通過key去找到value。不同類型的數(shù)據(jù)結(jié)構(gòu)的差異都是value的結(jié)構(gòu)不一樣。
字符串的一個常見的用處就是緩存用戶信息官觅,將用戶信息結(jié)構(gòu)體使用json序列化成字符串,然后將序列化的字符串存到redis中阐污。同樣取出用戶信息休涤,也要進行反序列化。
redis的字符串是動態(tài)字符串笛辟,可以修改的字符串功氨,內(nèi)部結(jié)構(gòu)類似與ArrayList,采用預(yù)分配空間來減少內(nèi)存的頻分分配手幢,內(nèi)部當(dāng)前的字符串空間要大于實際字符串長度捷凄。當(dāng)字符串小于1m的時候,擴容都是加倍現(xiàn)有的空間围来,如果超過1m跺涤,每次擴用只會擴1m。字符串的最大長度是512m

設(shè)置

#設(shè)置鍵值對
set key1 value1
#根據(jù)鍵獲取值
get key1
#判斷是否存在
exists key1
#刪除
del key1

批量操作

#設(shè)置
 mset key1 value1 key2 value2
#獲取
mget key1 key2

對key設(shè)置過期時間

#key1 5秒過期
expire key1 5 
#expire 等價 setex 
setex key2 5 value2
#如果 name 不存在就執(zhí)行 set 創(chuàng)建
setnx key1 value1

計數(shù)

 set age 30 
#自增
incr age
#減少6
incrby  age -6
#自增是有范圍的 在signed long之間

字符串有多個字節(jié)組成管钳,每個字節(jié)由8個bit組成钦铁,可將字符串看成多個bit組成,這邊是bitmap數(shù)據(jù)結(jié)構(gòu)[位圖]

list

list相當(dāng)于linkedList才漆,它是鏈表結(jié)構(gòu)牛曹,插入和刪除快,索引定位慢
當(dāng)彈出最后一個元素醇滥,該數(shù)據(jù)結(jié)構(gòu)被刪除黎比,內(nèi)存自動回收。
list常用來做異步隊列使用

  1. 隊列   左進右出
rpush key value1 value2
llen key
lpop key  #value1
lpop key # value2
  1. 椩妫  右進右出
rpush key value1 value2 
rpop key #value2
rpop key #value1
  1. 慢操作
    相當(dāng)于get(index)阅虫,需要對鏈表進行遍歷,隨著index的增大性能變慢不跟。ltrim跟著兩個參數(shù)(start_index,end_index)定義了一個區(qū)間颓帝,區(qū)間內(nèi)的保留,區(qū)間外的全部砍掉窝革」撼牵可以通過ltrim實現(xiàn)一個定長的鏈表。index可以為負(fù)數(shù)虐译,-1是倒數(shù)第一個元素瘪板,-2是倒數(shù)第二個元素
 rpush books python java golang 
 lindex books 1 # O(n) 慎用
 lrange books 0 -1 # 獲取所有元素,O(n) 慎用
 ltrim books 1 -1 # O(n) 慎用
lrange books 0 -1 
 ltrim books 1 0 # 這其實是清空了整個列表漆诽,因為區(qū)間范圍長度為負(fù)
  1. 快速列表
    redis底層存儲不是簡單的LinkedList 侮攀,而是一個快速列表quicklist的一個結(jié)構(gòu)
    首先锣枝,在列表元素較少的情況下,會使用一塊連續(xù)的內(nèi)存存儲兰英,稱之為ziplist撇叁,即壓縮列表。將所有的元素緊挨著存儲箭昵,分配的是一塊連續(xù)的內(nèi)存税朴。當(dāng)數(shù)據(jù)量大的時候會使用quicklist。因為普通的鏈表需要附件的指針空間太大家制,比較浪費空間,加重內(nèi)存的碎片化泡一。
    比如一個列表中只存int類型的數(shù)據(jù)颤殴,但是需要prev和next兩個額外的指針,所以將列表和ziplist結(jié)合起來組成了quiklist鼻忠。就是將多個ziplist使用雙向指針穿起來使用涵但。滿足了插入和刪除快,又不會出現(xiàn)太大的空間 冗余

字典hash

相當(dāng)于HashMap帖蔓。是無序字典矮瘟。內(nèi)部結(jié)構(gòu)和HashMap一致。是數(shù)組+鏈表的二維結(jié)構(gòu)塑娇。第一維數(shù)組的hash碰撞的時候澈侠,就會將碰撞的hash用鏈表存儲起來。
但是redis的字典只能是string 埋酬。另外和HashMap的rehash不一樣哨啃,reahs是一個很耗時的操作,HashMap在的字典很大的時候写妥,需要一次全部rehash拳球。而redis為可高性能,不能堵塞服務(wù)珍特,采用了漸進式rehash
漸進式rehash祝峻,會在rehash的同時,保留新舊兩個hash扎筒,查詢時會查詢兩個hash結(jié)構(gòu)莱找,然后在后續(xù)的定時任務(wù)以及hash的子指令中,將舊hash的內(nèi)容遷移到新hash中砸琅。當(dāng)舊hash移除最后一個元素宋距,該數(shù)據(jù)結(jié)構(gòu)被刪除,內(nèi)存被回收症脂。
hash結(jié)構(gòu)也可以存用戶信息谚赎,不同于字符串一次性需要全部 序列化整個對象淫僻,hash可以對用戶結(jié)構(gòu)的每個字段進行單獨存儲,當(dāng)需要獲取用戶信息可以進行部分獲取壶唤,而以字符串的形式進行存儲用戶信息只能一次性全部讀取完雳灵,比較浪費網(wǎng)絡(luò)流量。
hash也有缺點闸盔,hash結(jié)構(gòu)的存儲消耗要高于單個字符串悯辙,使用hash還是字符串根據(jù)實際情況來定。

> hset books java "think in java" # 命令行的字符串如果包含空格迎吵,要用引號括起來
(integer) 1
> hset books golang "concurrency in go"
(integer) 1
> hset books python "python cookbook"
(integer) 1
> hgetall books # entries()躲撰,key 和 value 間隔出現(xiàn)
1) "java"
2) "think in java"
3) "golang"
4) "concurrency in go"
5) "python"
6) "python cookbook"
> hlen books
(integer) 3
> hget books java
"think in java"
> hset books golang "learning go programming" # 因為是更新操作,所以返回 0
(integer) 0
> hget books golang "learning go programming"
> hmset books java "effective java" python "learning python" golang "modern golang
programming" # 批量 set
OK 

同字符串一樣击费,hash 結(jié)構(gòu)中的單個子 key 也可以進行計數(shù)拢蛋,它對應(yīng)的指令是 hincrby,
和 incr 使用基本一樣蔫巩。

> hincrby user-laoqian age 1
(integer) 30 

Set集合

相當(dāng)于HashSet谆棱,內(nèi)部的鍵值對是無序唯一的。內(nèi)部實現(xiàn)相當(dāng)于一個特殊的字典圆仔。字典中所有的value都有一個值NULL
當(dāng)集合中最后一個元素移除之后垃瞧,數(shù)據(jù)結(jié)構(gòu)自動刪除,內(nèi)存被回收坪郭。 set 結(jié)構(gòu)可以用來存儲活動中獎的用戶 ID个从,因為有去重功能,可以保證同一個用戶不會中獎兩次截粗。

> sadd books python
(integer) 1
> sadd bookspython # 重復(fù)
(integer) 0
> sadd books java golang
(integer) 2
> smembers books # 注意順序信姓,和插入的并不一致,因為 set 是無序的
1) "java"
2) "python"
3) "golang"
> sismember books java # 查詢某個 value 是否存在绸罗,相當(dāng)于 contains(o)
(integer) 1
> sismember books rust
(integer) 0
> scard books # 獲取長度相當(dāng)于 count()
(integer) 3
> spop books # 彈出一個
"java" 

zset (有序列表)

類似與HashMap和SortSet的結(jié)合意推。它是一個set,保證了內(nèi)部value的唯一性珊蟀,又給每個value賦予了score菊值,代表了value的排序權(quán)重。內(nèi)部實現(xiàn)是[跳躍列表]的數(shù)據(jù)結(jié)構(gòu)育灸。
zset 中最后一個 value 被移除后腻窒,數(shù)據(jù)結(jié)構(gòu)自動刪除,內(nèi)存被回收磅崭。 zset 可以用來存粉絲列表儿子,value 值是粉絲的用戶 ID,score 是關(guān)注時間砸喻。我們可以對粉絲列表按關(guān)注時間進行排序柔逼。
zset 還可以用來存儲學(xué)生的成績蒋譬,value 值是學(xué)生的 ID,score 是他的考試成績愉适。我們可以對成績按分?jǐn)?shù)進行排序就可以得到他的名次犯助。

> zadd books 9.0 "think in java" 
(integer) 1 
> zadd books 8.9 "java concurrency" 
(integer) 1 
> zadd books 8.6 "java cookbook" 
(integer) 1 
> zrange books 0 -1 # 按 score 排序列出,參數(shù)區(qū)間為排名范圍
1) "java cookbook" 
2) "java concurrency" 
3) "think in java" 
> zrevrange books 0 -1 # 按 score 逆序列出维咸,參數(shù)區(qū)間為排名范圍
1) "think in java" 
2) "java concurrency" 
3) "java cookbook" 
> zcard books # 相當(dāng)于 count()
(integer) 3 
> zscore books "java concurrency" # 獲取指定 value 的 score
"8.9000000000000004" # 內(nèi)部 score 使用 double 類型進行存儲剂买,所以存在小數(shù)點精度問題
> zrank books "java concurrency" # 排名
(integer) 1 
> zrangebyscore books 0 8.91 # 根據(jù)分值區(qū)間遍歷 zset
1) "java cookbook" 
2) "java concurrency" 
> zrangebyscore books -inf 8.91 withscores # 根據(jù)分值區(qū)間 (-∞, 8.91] 遍歷 zset,同時返
回分值癌蓖。inf 代表 infinite瞬哼,無窮大的意思。
1) "java cookbook" 
2) "8.5999999999999996" 
3) "java concurrency" 
4) "8.9000000000000004" 
> zrem books "java concurrency" # 刪除 value
(integer) 1 
> zrange books 0 -1 
1) "java cookbook" 
2) "think in java"

跳躍列表

因為zset支持隨機插入和刪除费坊,所以不好使用數(shù)組表示倒槐,采用跳躍列表。



跳躍列表中的元素可以身兼數(shù)職附井,如上圖中間的元素,同時處于L0两残,L1永毅,L2中,可以快速在不同層級進行跳躍人弓。
定位插入點時沼死,先在頂層進行定位,然后下潛到下一級定位崔赌,一直下潛到最底層找到合適的位置意蛀,將新元素插進去。你也許會問健芭,那新插入的元素如何才有機會「身兼數(shù)職」呢县钥?
跳躍列表采取一個隨機策略來決定新元素可以兼職到第幾層。
首先 L0 層肯定是 100% 了慈迈,L1 層只有 50% 的概率若贮,L2 層只有 25% 的概率,L3 層只有 12.5% 的概率痒留,一直隨機到最頂層 L31 層谴麦。絕大多數(shù)元素都過不了幾層,只有極少數(shù)元素可以深入到頂層伸头。列表中的元素越多匾效,能夠深入的層次就越深,能進入到頂層的概率就會越大恤磷。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末面哼,一起剝皮案震驚了整個濱河市野宜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌精绎,老刑警劉巖速缨,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異代乃,居然都是意外死亡旬牲,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門搁吓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來原茅,“玉大人,你說我怎么就攤上這事堕仔±揲伲” “怎么了?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵摩骨,是天一觀的道長通贞。 經(jīng)常有香客問我,道長恼五,這世上最難降的妖魔是什么昌罩? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮灾馒,結(jié)果婚禮上茎用,老公的妹妹穿的比我還像新娘。我一直安慰自己睬罗,他們只是感情好轨功,可當(dāng)我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著容达,像睡著了一般古涧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上董饰,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天蒿褂,我揣著相機與錄音,去河邊找鬼卒暂。 笑死啄栓,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的也祠。 我是一名探鬼主播昙楚,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼诈嘿!你這毒婦竟也來了堪旧?” 一聲冷哼從身側(cè)響起削葱,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎淳梦,沒想到半個月后析砸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡爆袍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年首繁,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片陨囊。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡弦疮,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蜘醋,到底是詐尸還是另有隱情胁塞,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布压语,位于F島的核電站啸罢,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏胎食。R本人自食惡果不足惜伺糠,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望斥季。 院中可真熱鬧,春花似錦累驮、人聲如沸酣倾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽躁锡。三九已至,卻和暖如春置侍,著一層夾襖步出監(jiān)牢的瞬間映之,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工蜡坊, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留杠输,地道東北人。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓秕衙,卻偏偏與公主長得像蠢甲,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子据忘,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,864評論 2 354