一、Redis的概念
Redis是一個基于內存的高性能key-value數據庫。
Redis本質上是一個Key-Value類型的內存數據庫,很像memcached,整個數據庫統統加載在內存當中進行操作,定期通過異步操作把數據庫數據flush到硬盤上進行保存。因為是純內存操作,Redis的性能非常出色,每秒可以處理超過 10萬次讀寫操作,是已知性能最快的Key-Value DB。
Redis 與其他 key – value 緩存產品有以下三個特點:
- Redis支持數據的持久化,可以將內存中的數據保持在磁盤中,重啟的時候可以再次加載進行使用。
- Redis不僅僅支持簡單的key-value類型的數據,同時還提供list,set,zset,hash等數據結構的存儲。
- Redis支持數據的備份,即master-slave模式的數據備份。
二、Redis的五種常用的數據類型
Redis的五種常用的數據類型分別是:String、Hash、List、Set和Sorted set
1 String
常用命令:
set/get/decr/incr/mget等;
應用場景:
String是最常用的一種數據類型,普通的key/value存儲都可以歸為此類;
實現方式:
String在redis內部存儲默認就是一個字符串,被redisObject所引用,當遇到incr、decr等操作時會轉成數值型進行計算,此時redisObject的encoding字段為int。
2 Hash
常用命令:
hget/hset/hgetall等
應用場景:
我們要存儲一個用戶信息對象數據,其中包括用戶ID、用戶姓名、年齡和生日,通過用戶ID我們希望獲取該用戶的姓名或者年齡或者生日;
實現方式:
Redis的Hash實際是內部存儲的Value為一個HashMap,并提供了直接存取這個Map成員的接口。如圖所示,Key是用戶ID, value是一個Map。這個Map的key是成員的屬性名,value是屬性值。這樣對數據的修改和存取都可以直接通過其內部Map的Key(Redis里稱內部Map的key為field), 也就是通過 key(用戶ID) + field(屬性標簽) 就可以操作對應屬性數據。當前HashMap的實現有兩種方式:當HashMap的成員比較少時Redis為了節省內存會采用類似一維數組的方式來緊湊存儲,而不會采用真正的HashMap結構,這時對應的value的redisObject的encoding為zipmap,當成員數量增大時會自動轉成真正的HashMap,此時encoding為int。
3 List
常用命令:
lpush/rpush/lpop/rpop/lrange等;
應用場景:
Redis list的應用場景非常多,也是Redis最重要的數據結構之一,比如twitter的關注列表,粉絲列表等都可以用Redis的list結構來實現;
實現方式:
Redis list的實現為一個雙向鏈表,即可以支持反向查找和遍歷,更方便操作,不過帶來了部分額外的內存開銷,Redis內部的很多實現,包括發送緩沖隊列等也都是用的這個數據結構。
4 Set
常用命令:
sadd/spop/smembers/sunion等;
應用場景:
Redis set對外提供的功能與list類似是一個列表的功能,特殊之處在于set是可以自動排重的,當你需要存儲一個列表數據,又不希望出現重復數據時,set是一個很好的選擇,并且set提供了判斷某個成員是否在一個set集合內的重要接口,這個也是list所不能提供的;
實現方式:
set 的內部實現是一個 value永遠為null的HashMap,實際就是通過計算hash的方式來快速排重的,這也是set能提供判斷一個成員是否在集合內的原因。
5 Sorted Set
常用命令:
zadd/zrange/zrem/zcard等;
應用場景:
Redis sorted set的使用場景與set類似,區別是set不是自動有序的,而sorted set可以通過用戶額外提供一個優先級(score)的參數來為成員排序,并且是插入有序的,即自動排序。當你需要一個有序的并且不重復的集合列表,那么可以選擇sorted set數據結構,比如twitter 的public timeline可以以發表時間作為score來存儲,這樣獲取時就是自動按時間排好序的。
實現方式:
Redis sorted set的內部使用HashMap和跳躍表(SkipList)來保證數據的存儲和有序,HashMap里放的是成員到score的映射,而跳躍表里存放的是所有的成員,排序依據是HashMap里存的score,使用跳躍表的結構可以獲得比較高的查找效率,并且在實現上比較簡單。
三、Redis的內存淘汰機制
Redis提供了下面幾種淘汰策略供用戶選擇,其中默認的策略為noeviction策略:
- noeviction:當內存使用達到閾值的時候,所有引起申請內存的命令會報錯。
- allkeys-lru:在主鍵空間中,優先移除最近未使用的key。
- volatile-lru:在設置了過期時間的鍵空間中,優先移除最近未使用的key。
- allkeys-random:在主鍵空間中,隨機移除某個key。
- volatile-random:在設置了過期時間的鍵空間中,隨機移除某個key。
- volatile-ttl:在設置了過期時間的鍵空間中,具有更早過期時間的key優先移除。
詳見:Redis 內存淘汰機制
四、Redis的復制機制
詳見:淺析Redis復制
五、Redis 和 Memcached 的區別
Redis支持服務器端的數據操作:Redis相比Memcached來說,擁有更多的數據結構和并支持更豐富的數據操作,通常在Memcached里,你需要將數據拿到客戶端來進行類似的修改再set回去。這大大增加了網絡IO的次數和數據體積。在Redis中,這些復雜的操作通常和一般的GET/SET一樣高效。所以,如果需要緩存能夠支持更復雜的結構和操作,那么Redis會是不錯的選擇。
內存使用效率對比:使用簡單的key-value存儲的話,Memcached的內存利用率更高,而如果Redis采用hash結構來做key-value存儲,由于其組合式的壓縮,其內存利用率會高于Memcached。
性能對比:由于Redis只使用單核,而Memcached可以使用多核,所以平均每一個核上Redis在存儲小數據時比Memcached性能更高。而在100k以上的數據中,Memcached性能要高于Redis,雖然Redis最近也在存儲大數據的性能上進行優化,但是比起Memcached,還是稍有遜色。