一、Redis的概念
Redis是一個基于內(nèi)存的高性能key-value數(shù)據(jù)庫分歇。
Redis本質(zhì)上是一個Key-Value類型的內(nèi)存數(shù)據(jù)庫傀蓉,很像memcached,整個數(shù)據(jù)庫統(tǒng)統(tǒng)加載在內(nèi)存當(dāng)中進(jìn)行操作职抡,定期通過異步操作把數(shù)據(jù)庫數(shù)據(jù)flush到硬盤上進(jìn)行保存葬燎。因?yàn)槭羌儍?nèi)存操作,Redis的性能非常出色缚甩,每秒可以處理超過 10萬次讀寫操作谱净,是已知性能最快的Key-Value DB。
Redis 與其他 key – value 緩存產(chǎn)品有以下三個特點(diǎn):
- Redis支持?jǐn)?shù)據(jù)的持久化蹄胰,可以將內(nèi)存中的數(shù)據(jù)保持在磁盤中岳遥,重啟的時候可以再次加載進(jìn)行使用奕翔。
- Redis不僅僅支持簡單的key-value類型的數(shù)據(jù)裕寨,同時還提供list,set派继,zset宾袜,hash等數(shù)據(jù)結(jié)構(gòu)的存儲。
- Redis支持?jǐn)?shù)據(jù)的備份驾窟,即master-slave模式的數(shù)據(jù)備份庆猫。
二、Redis的五種常用的數(shù)據(jù)類型
Redis的五種常用的數(shù)據(jù)類型分別是:String绅络、Hash月培、List嘁字、Set和Sorted set
1 String
常用命令:
set/get/decr/incr/mget等;
應(yīng)用場景:
String是最常用的一種數(shù)據(jù)類型杉畜,普通的key/value存儲都可以歸為此類纪蜒;
實(shí)現(xiàn)方式:
String在redis內(nèi)部存儲默認(rèn)就是一個字符串,被redisObject所引用此叠,當(dāng)遇到incr纯续、decr等操作時會轉(zhuǎn)成數(shù)值型進(jìn)行計(jì)算,此時redisObject的encoding字段為int灭袁。
2 Hash
常用命令:
hget/hset/hgetall等
應(yīng)用場景:
我們要存儲一個用戶信息對象數(shù)據(jù)猬错,其中包括用戶ID、用戶姓名茸歧、年齡和生日倦炒,通過用戶ID我們希望獲取該用戶的姓名或者年齡或者生日;
實(shí)現(xiàn)方式:
Redis的Hash實(shí)際是內(nèi)部存儲的Value為一個HashMap举娩,并提供了直接存取這個Map成員的接口析校。如圖所示,Key是用戶ID, value是一個Map铜涉。這個Map的key是成員的屬性名智玻,value是屬性值。這樣對數(shù)據(jù)的修改和存取都可以直接通過其內(nèi)部Map的Key(Redis里稱內(nèi)部Map的key為field), 也就是通過 key(用戶ID) + field(屬性標(biāo)簽) 就可以操作對應(yīng)屬性數(shù)據(jù)芙代。當(dāng)前HashMap的實(shí)現(xiàn)有兩種方式:當(dāng)HashMap的成員比較少時Redis為了節(jié)省內(nèi)存會采用類似一維數(shù)組的方式來緊湊存儲吊奢,而不會采用真正的HashMap結(jié)構(gòu),這時對應(yīng)的value的redisObject的encoding為zipmap纹烹,當(dāng)成員數(shù)量增大時會自動轉(zhuǎn)成真正的HashMap,此時encoding為int页滚。
3 List
常用命令:
lpush/rpush/lpop/rpop/lrange等;
應(yīng)用場景:
Redis list的應(yīng)用場景非常多铺呵,也是Redis最重要的數(shù)據(jù)結(jié)構(gòu)之一裹驰,比如twitter的關(guān)注列表,粉絲列表等都可以用Redis的list結(jié)構(gòu)來實(shí)現(xiàn)片挂;
實(shí)現(xiàn)方式:
Redis list的實(shí)現(xiàn)為一個雙向鏈表幻林,即可以支持反向查找和遍歷,更方便操作音念,不過帶來了部分額外的內(nèi)存開銷沪饺,Redis內(nèi)部的很多實(shí)現(xiàn),包括發(fā)送緩沖隊(duì)列等也都是用的這個數(shù)據(jù)結(jié)構(gòu)闷愤。
4 Set
常用命令:
sadd/spop/smembers/sunion等整葡;
應(yīng)用場景:
Redis set對外提供的功能與list類似是一個列表的功能,特殊之處在于set是可以自動排重的讥脐,當(dāng)你需要存儲一個列表數(shù)據(jù)遭居,又不希望出現(xiàn)重復(fù)數(shù)據(jù)時啼器,set是一個很好的選擇,并且set提供了判斷某個成員是否在一個set集合內(nèi)的重要接口俱萍,這個也是list所不能提供的镀首;
實(shí)現(xiàn)方式:
set 的內(nèi)部實(shí)現(xiàn)是一個 value永遠(yuǎn)為null的HashMap,實(shí)際就是通過計(jì)算hash的方式來快速排重的鼠次,這也是set能提供判斷一個成員是否在集合內(nèi)的原因更哄。
5 Sorted Set
常用命令:
zadd/zrange/zrem/zcard等;
應(yīng)用場景:
Redis sorted set的使用場景與set類似腥寇,區(qū)別是set不是自動有序的成翩,而sorted set可以通過用戶額外提供一個優(yōu)先級(score)的參數(shù)來為成員排序,并且是插入有序的赦役,即自動排序麻敌。當(dāng)你需要一個有序的并且不重復(fù)的集合列表,那么可以選擇sorted set數(shù)據(jù)結(jié)構(gòu)掂摔,比如twitter 的public timeline可以以發(fā)表時間作為score來存儲术羔,這樣獲取時就是自動按時間排好序的。
實(shí)現(xiàn)方式:
Redis sorted set的內(nèi)部使用HashMap和跳躍表(SkipList)來保證數(shù)據(jù)的存儲和有序乙漓,HashMap里放的是成員到score的映射级历,而跳躍表里存放的是所有的成員,排序依據(jù)是HashMap里存的score,使用跳躍表的結(jié)構(gòu)可以獲得比較高的查找效率叭披,并且在實(shí)現(xiàn)上比較簡單寥殖。
三、Redis的內(nèi)存淘汰機(jī)制
Redis提供了下面幾種淘汰策略供用戶選擇涩蜘,其中默認(rèn)的策略為noeviction策略:
- noeviction:當(dāng)內(nèi)存使用達(dá)到閾值的時候嚼贡,所有引起申請內(nèi)存的命令會報(bào)錯。
- allkeys-lru:在主鍵空間中同诫,優(yōu)先移除最近未使用的key粤策。
- volatile-lru:在設(shè)置了過期時間的鍵空間中,優(yōu)先移除最近未使用的key误窖。
- allkeys-random:在主鍵空間中叮盘,隨機(jī)移除某個key。
- volatile-random:在設(shè)置了過期時間的鍵空間中贩猎,隨機(jī)移除某個key熊户。
- volatile-ttl:在設(shè)置了過期時間的鍵空間中萍膛,具有更早過期時間的key優(yōu)先移除吭服。
四、Redis的復(fù)制機(jī)制
五蝗罗、Redis 和 Memcached 的區(qū)別
Redis支持服務(wù)器端的數(shù)據(jù)操作:Redis相比Memcached來說艇棕,擁有更多的數(shù)據(jù)結(jié)構(gòu)和并支持更豐富的數(shù)據(jù)操作蝌戒,通常在Memcached里,你需要將數(shù)據(jù)拿到客戶端來進(jìn)行類似的修改再set回去沼琉。這大大增加了網(wǎng)絡(luò)IO的次數(shù)和數(shù)據(jù)體積北苟。在Redis中,這些復(fù)雜的操作通常和一般的GET/SET一樣高效打瘪。所以友鼻,如果需要緩存能夠支持更復(fù)雜的結(jié)構(gòu)和操作,那么Redis會是不錯的選擇闺骚。
內(nèi)存使用效率對比:使用簡單的key-value存儲的話彩扔,Memcached的內(nèi)存利用率更高,而如果Redis采用hash結(jié)構(gòu)來做key-value存儲僻爽,由于其組合式的壓縮虫碉,其內(nèi)存利用率會高于Memcached。
性能對比:由于Redis只使用單核胸梆,而Memcached可以使用多核敦捧,所以平均每一個核上Redis在存儲小數(shù)據(jù)時比Memcached性能更高。而在100k以上的數(shù)據(jù)中碰镜,Memcached性能要高于Redis兢卵,雖然Redis最近也在存儲大數(shù)據(jù)的性能上進(jìn)行優(yōu)化,但是比起Memcached绪颖,還是稍有遜色济蝉。