1.1 Redis基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)
1.1.1 Redis的安裝
體驗(yàn)Redis需要使用Linux
或者Mac
環(huán)境,redis的安裝主要有以下三種方式。
- 使用Docker安裝
- 通關(guān)Github源碼編譯
- 直接安裝
apt-get install
(Ubuntu)葫慎、yun install
(RedHat)或者brew install
(Mac)
1.1.2 Redis的5種數(shù)據(jù)結(jié)構(gòu)
? Redis有5中數(shù)據(jù)結(jié)構(gòu),分別為:String
(字符串)纽窟、list
(列表)、hash
(字典)兼吓、set
(集合)臂港、zset
(有序集合)。
String(字符串)
? Redis的字符串是動(dòng)態(tài)字符串视搏,是可以修改的字符串审孽,內(nèi)部機(jī)構(gòu)的實(shí)現(xiàn)類似于Java的ArrayList
,采用預(yù)分配冗余空間的方式來(lái)減少內(nèi)存的頻繁分配浑娜。
List(列表)
? Redis的列表相當(dāng)于Java語(yǔ)言里的LinkedList佑力,這意味著list的插入和刪除操作非常快棚愤,但索引定位很慢搓萧。
? Redis的列表結(jié)構(gòu)常用來(lái)做異步隊(duì)列使用。
? 如果再深入一點(diǎn)宛畦,你會(huì)發(fā)現(xiàn)Redis底層存儲(chǔ)的不是一個(gè)簡(jiǎn)單linkedList,而是稱職為“快速鏈表”(quickList)的一個(gè)結(jié)構(gòu)揍移。
? 在列表元素較少的情況下次和,會(huì)使用一塊連續(xù)的內(nèi)存存儲(chǔ),這個(gè)機(jī)構(gòu)是zipList那伐,即壓縮列表踏施。它將所有的元素彼此緊挨著一起存儲(chǔ)石蔗,分配的是一塊連續(xù)的內(nèi)存。當(dāng)數(shù)據(jù)量比較多的時(shí)候才會(huì)改成quickList畅形。Redis將鏈表和zipList結(jié)合起來(lái)組成了quickList养距,也就是將多個(gè)zipList使用雙向指針串起來(lái)使用。quickList既滿足了快速的插入刪除性能日熬,又不會(huì)出現(xiàn)太大的冗余空間棍厌。
hash(字典)
? Redis的字典相當(dāng)于Java語(yǔ)言里的HashMap,它是無(wú)序字典竖席,內(nèi)部存儲(chǔ)了很多鍵值對(duì)耘纱。實(shí)現(xiàn)結(jié)構(gòu)上與Java的HashMap也是一樣的,都是==數(shù)組==+==鏈表==的二維結(jié)構(gòu)毕荐。但他們的rehash
的方式不一樣束析,Redis為了追求高性能,采用了漸進(jìn)式rehash策略憎亚。
? 漸進(jìn)式rehash會(huì)在rehash的同時(shí)员寇,保留新舊兩個(gè)hash結(jié)構(gòu),查詢時(shí)會(huì)同時(shí)查詢兩個(gè)hash結(jié)構(gòu)第美,循環(huán)漸進(jìn)地將舊hash的內(nèi)同一點(diǎn)點(diǎn)地遷移到新的hash結(jié)構(gòu)中蝶锋,最后使用新的hash結(jié)構(gòu)取而代之。
? hash結(jié)構(gòu)可以用來(lái)存儲(chǔ)用戶信息斋日,與字符串需要一次性全部序列化整個(gè)用戶對(duì)象不用牲览,hash可以對(duì)用戶結(jié)構(gòu)中的每個(gè)字段單獨(dú)存儲(chǔ)。這樣當(dāng)我們需要獲去用戶信息時(shí)可以進(jìn)行部分獲取恶守。而以字符串的形式去保存用戶信息的話第献,就只能一次性全部讀取,這樣就會(huì)浪費(fèi)網(wǎng)絡(luò)流量兔港。
? 個(gè)人遇到過(guò)Redis獲取一個(gè)完整的商戶信息字符串庸毫,有一萬(wàn)多個(gè)字符,大于28k的內(nèi)存
? hash也有缺點(diǎn)衫樊,hash結(jié)構(gòu)的存儲(chǔ)消耗要高于單個(gè)字符串飒赃。
set(集合)
? Redis的集合相當(dāng)于Java語(yǔ)言里的HashSet
,它內(nèi)部的鍵值對(duì)是無(wú)序的科侈、唯一的载佳。它的內(nèi)部實(shí)現(xiàn)相當(dāng)于一個(gè)特殊的字典,字典中所有的value都是一個(gè)值NULL
臀栈。
set結(jié)構(gòu)可以用來(lái)存儲(chǔ)在某活動(dòng)中中將的用戶ID蔫慧,因?yàn)橛腥ブ毓δ埽梢员WC同一個(gè)用戶不會(huì)中將兩次权薯。
zset(有序集合)
? 它類似于Java的SortedSet
和HashMap
的結(jié)合體姑躲,相當(dāng)于一個(gè)有序set.睡扬。它的內(nèi)部實(shí)現(xiàn)是一種叫做==“跳躍列表”==的數(shù)據(jù)結(jié)構(gòu)。
? 跳躍列表是在一個(gè)鏈表中黍析,每隔幾個(gè)元素選出一個(gè)代表元素卖怜,然后用一級(jí)指針串起來(lái),再?gòu)倪@寫被串起來(lái)的代表中再選出一些代表元素阐枣,最終形成了一個(gè)金字塔結(jié)構(gòu)马靠。定位插入點(diǎn)時(shí),現(xiàn)在最頂層進(jìn)行定位侮繁,然后一級(jí)一級(jí)下潛到最底層找到合適的位置虑粥,將新元素插進(jìn)去。
1.1.3 容器型數(shù)據(jù)結(jié)構(gòu)的通用規(guī)則
list宪哩、set娩贷、hash、zset這四縱數(shù)據(jù)結(jié)構(gòu)是容器型數(shù)據(jù)結(jié)構(gòu)锁孟,共享以下兩條原則:
- create if not exists: 如果容器不存在彬祖,那就創(chuàng)建一個(gè),再進(jìn)行操作品抽。
- drop uf no elements: 如果容器里的元素沒(méi)有了储笑,那么立即刪除容器,釋放內(nèi)存圆恤。
1.1.4 過(guò)期時(shí)間
? Redis所有的數(shù)據(jù)結(jié)構(gòu)都可以設(shè)置過(guò)期時(shí)間突倍。過(guò)期是以對(duì)象為單位。
? 如果一個(gè)字符串以及設(shè)置了過(guò)期時(shí)間盆昙,然后你調(diào)用set方法修改了它羽历,那么它的過(guò)期時(shí)間會(huì)消失。