Redis簡述
html
Redis 是徹底開源免費的,遵照BSD協議,先進的key - value持久化產品。它一般被稱爲數據結構服務器,由於值(value)能夠是 字符串(String), 哈希(Map), 列表(list), 集合(sets) 和 有序集合(sorted sets)等類型。
redis
redis 是一個高性能的key-value數據庫。 redis的出現,很大程度補償了memcached這類keyvalue存儲的不足,在部 分場合能夠對關係數據庫起到很好的補充做用。它提供了Python,Ruby,Erlang,PHP客戶端,使用很方便。問題是這個項目還很新,可能還不足夠穩定,並且沒有在實際的一些大型系統應用的實例。此外,缺少mc中批量get也是比較大的問題,始終批量獲取跟屢次獲取的網絡開銷是不同的。
性能測試結果:
SET操做每秒鐘 110000 次,GET操做每秒鐘 81000 次,服務器配置以下:
Linux 2.6, Xeon X3320 2.5Ghz.
stackoverflow 網站使用 Redis 作爲緩存服務器。數據庫
安裝過程:
Redis是一種高級key-value數據庫。它跟memcached相似,不過數據能夠持久化,並且支持的數據類型很豐富。有字符串,鏈表,集 合和有序集合。支持在服務器端計算集合的並,交和補集(difference)等,還支持多種排序功能。因此Redis也能夠被當作是一個數據結構服務 器。數組
Redis的全部數據都是保存在內存中,而後不按期的經過異步方式保存到磁盤上(這稱爲「半持久化模式」);也能夠把每一次數據變化都寫入到一個append only file(aof)裏面(這稱爲「全持久化模式」)。緩存
一、redis 中的每個數據庫,都由一個 redisDb 的結構存儲。其中,redisDb.id 存儲着 redis 數據庫以整數表示的號碼。redisDb.dict 存儲着該庫全部的鍵值對數據。redisDb.expires 保存着每個鍵的過時時間。 二、當redis 服務器初始化時,會預先分配 16 個數據庫(該數量能夠經過配置文件配置),全部數據庫保存到結構 redisServer 的一個成員 redisServer.db 數組中。當咱們選擇數據庫 select number 時,程序直接經過 redisServer.db[number] 來切換數據庫。有時候當程序須要知道本身是在哪一個數據庫時,直接讀取 redisDb.id 便可。 三、既然咱們知道一個數據庫的全部鍵值都存儲在redisDb.dict中,那麼咱們要知道若是找到key的位置,就有必要了解一下dict 的結構了: typedef struct dict { // 特定於類型的處理函數 dictType *type; // 類型處理函數的私有數據 void *privdata; // 哈希表(2個) dictht ht[2]; // 記錄 rehash 進度的標誌,值爲-1 表示 rehash 未進行 int rehashidx; // 當前正在運做的安全迭代器數量 int iterators; } dict; 由上述的結構能夠看出,redis 的字典使用哈希表做爲其底層實現。dict 類型使用的兩個指向哈希表的指針,其中 0 號哈希表(ht[0])主要用於存儲數據庫的全部鍵值,而1號哈希表主要用於程序對 0 號哈希表進行 rehash 時使用,rehash 通常是在添加新值時會觸發,這裏不作過多的贅述。因此redis 中查找一個key,其實就是對進行該dict 結構中的 ht[0] 進行查找操做。 四、既然是哈希,那麼咱們知道就會有哈希碰撞,那麼當多個鍵哈希以後爲同一個值怎麼辦呢?redis採起鏈表的方式來存儲多個哈希碰撞的鍵。也就是說,當根據key的哈希值找到該列表後,若是列表的長度大於1,那麼咱們須要遍歷該鏈表來找到咱們所查找的key。固然,通常狀況下鏈表長度都爲是1,因此時間複雜度可看做o(1)。
redis下,數據庫是由一個整數索引標識,而不是由一個數據庫名稱。默認狀況下,一個客戶端鏈接到數據庫0。redis配置文件中下面的參數來控制數據庫總數:
安全
默認狀況下是16個。修改redis.conf下的databases指令:服務器
databases 16網絡
能夠經過下面的命令來切換到不一樣的數據庫下
數據結構
select 2
app
Redis最爲經常使用的數據類型主要有如下五種:
●String
●Hash
●List
●Set
●Sorted set
set,get,decr,incr,mget
hget,hset,hgetall
lpush,rpush,lpop,rpop,lrange
sadd,spop,smembers,sunion
zadd,zrange,zrem,zcard
Redis的持久化機制
Redis因爲支持很是豐富的內存數據結構類型,如何把這些複雜的內存組織方式持久化到磁盤上是一個難題,因此Redis的持久化方式與傳統數據庫的方式有比較多的差異,Redis一共支持四種持久化方式,分別是:
●定時快照方式(snapshot)
●基於語句追加文件的方式(aof)
●虛擬內存(vm)
●Diskstore方式
常用內存優化手段與參數
經過咱們上面的一些實現上的分析能夠看出redis實際上的內存管理成本很是高,即佔用了過多的內存,做者對這點也非常清楚,因此提供了一系列的參數和手段來控制和節省內存,咱們分別來討論下。
首先最重要的一點是不要開啓Redis的VM選項,即虛擬內存功能,這個原本是做爲Redis存儲超出物理內存數據的一種數據在內存與磁盤換入換出的一個持久化策略,可是其內存管理成本也很是的高,而且咱們後續會分析此種持久化策略並不成熟,因此要關閉VM功能,請檢查你的redis.conf文件中vm-enabled 爲 no。
其次最好設置下redis.conf中的maxmemory選項,該選項是告訴Redis當使用了多少物理內存後就開始拒絕後續的寫入請求,該參數能很好的保護好你的Redis不會由於使用了過多的物理內存而致使swap,最終嚴重影響性能甚至崩潰。
另外Redis爲不一樣數據類型分別提供了一組參數來控制內存使用,咱們在前面詳細分析過RedisHash是value內部爲一個HashMap,若是該Map的成員數比較少,則會採用相似一維線性的緊湊格式來存儲該Map,即省去了大量指針的內存開銷,這個參數控制對應在redis.conf配置文件中下面2項:
hash-max-zipmap-entries 64
hash-max-zipmap-value 512
hash-max-zipmap-entries
含義是當value這個Map內部不超過多少個成員時會採用線性緊湊格式存儲,默認是64,即value內部有64個如下的成員就是使用線性緊湊存儲,超過該值自動轉成真正的HashMap。
hash-max-zipmap-value 含義是當value這個Map內部的每一個成員值長度不超過多少字節就會採用線性緊湊存儲來節省空間。
以上2個條件任意一個條件超過設置值都會轉換成真正的HashMap,也就不會再節省內存了,那麼這個值是否是設置的越大越好呢,答案固然是否認的,HashMap的優點就是查找和操做的時間複雜度都是O(1)的,而放棄Hash採用一維存儲則是O(n)的時間複雜度,若是
成員數量不多,則影響不大,不然會嚴重影響性能,因此要權衡好這個值的設置,整體上仍是最根本的時間成本和空間成本上的權衡。
一樣相似的參數還有:
list-max-ziplist-entries 512
說明:list數據類型多少節點如下會採用去指針的緊湊存儲格式。
list-max-ziplist-value 64
說明:list數據類型節點值大小小於多少字節會採用緊湊存儲格式。
set-max-intset-entries 512
說明:set數據類型內部數據若是所有是數值型,且包含多少節點如下會採用緊湊格式存儲。
最後想說的是Redis內部實現沒有對內存分配方面作過多的優化,在必定程度上會存在內存碎片,不過大多數狀況下這個不會成爲Redis的性能瓶頸,不過若是在Redis內部存儲的大部分數據是數值型的話,Redis內部採用了一個sharedinteger的方式來省去分配內存的開銷,即在系統啓動時先分配一個從1~n那麼多個數值對象放在一個池子中,若是存儲的數據剛好是這個數值範圍內的數據,則直接從池子裏取出該對象,而且經過引用計數的方式來共享,這樣在系統存儲了大量數值下,也能必定程度上節省內存而且提升性能,這個參數值n的設置須要修改源代碼中的一行宏定義REDIS_SHARED_INTEGERS,該值默認是10000,能夠根據本身的須要進行修改,修改後從新編譯就能夠了。
總結:
1.根據業務須要選擇合適的數據類型,併爲不一樣的應用場景設置相應的緊湊存儲參數。
2.當業務場景不須要數據持久化時,關閉全部的持久化方式能夠得到最佳的性能以及最大的內存使用量。
3.若是須要使用持久化,根據是否能夠容忍重啓丟失部分數據在快照方式與語句追加方式之間選擇其一,不要使用虛擬內存以及diskstore方式。
4.不要讓你的Redis所在機器物理內存使用超過實際內存總量的3/5。
Redis Desktop Manager
Redis Desktop Manager 是一個快速、簡單、支持跨平臺的 Redis 桌面管理工具,基於 Qt 5 開發,支持經過 SSH Tunnel 鏈接。