Redis基礎 高階特性與效能調優

2021-09-24 08:25:44 字數 2838 閱讀 4001

記憶體管理優化

redis hash是value內部為乙個hashmap,如果該map的成員數比較少,則會採用類似一維線性的緊湊格式來儲存該map, 即省去了大量指標的記憶體開銷,這個引數控制對應在redis.conf配置檔案中下面2項:

hash-max-zipmap-entries 64 hash-max-zipmap-value 512

當value這個map內部不超過多少個成員時會採用線性緊湊格式儲存,預設是64,即value內部有64個以下的成員就是使用線性緊湊儲存,超過該值自動轉成真正的hashmap。

hash-max-zipmap-value 含義是當 value這個map內部的每個成員值長度不超過多少位元組就會採用線性緊湊儲存來節省空間。

以上2個條件任意乙個條件超過設定值都會轉換成真正的hashmap,也就不會再節省記憶體了,那麼這個值是不是設定的越大越好呢,答案當然是否定的,hashmap的優勢就是查詢和操作的時間複雜度都是o(1)的,而放棄hash採用一維儲存則是o(n)的時間複雜度,如果

成員數量很少,則影響不大,否則會嚴重影響效能,所以要權衡好這個值的設定,總體上還是最根本的時間成本和空間成本上的權衡。

list-max-ziplist-value 64 list-max-ziplist-entries 512

list資料型別節點值大小小於多少位元組會採用緊湊儲存格式、list資料型別多少節點以下會採用去指標的緊湊儲存格式。

記憶體預分配:

redis內部實現沒有對記憶體分配方面做過多的優化(對比memcache),在一定程度上會存在記憶體碎片,不過大多數情況下這個不會成為redis的效能瓶頸,不過如果在redis內部儲存的大部分資料是數值型的話,redis內部採用了乙個shared integer的 方式來省去分配記憶體的開銷,即在系統啟動時先分配乙個從1~n 那麼多個數值物件放在乙個池子中,如果儲存的資料恰好是這個數值範圍內的資料,則直接從池子裡取出該物件,並且通過引用計數的方式來共享,這樣在系統儲存 了大量數值下,也能一定程度上節省記憶體並且提高效能,這個引數值n的設定需要修改源**中的一行巨集定義redis_shared_integers,該值 預設是10000,可以根據自己的需要進行修改,修改後重新編譯就可以了。

持久化機制:

定時快照方式(snapshot):

該持久化方式實際是在redis內部乙個定時器事件,每隔固定時間去檢查當前資料發生的改變次數與時間是否滿足配置的持久化觸發的條件,如果滿足則通 過作業系統fork呼叫來建立出乙個子程序,這個子程序缺省會與父程序共享相同的位址空間,這時就可以通過子程序來遍歷整個記憶體來進行儲存操作,而主程序 則仍然可以提供服務,當有寫入時由作業系統按照記憶體頁(page)為單位來進行copy-on-write保證父子程序之間不會互相影響。

該持久化的主要缺點是定時快照只是代表一段時間內的記憶體映像,所以系統重啟會丟失上次快照與重啟之間所有的資料。

基於語句追加方式(aof):

aof方式實際類似mysql的基於語句的binlog方式,即每條會使redis記憶體資料發生改變的命令都會追加到乙個log檔案中,也就是說這個log檔案就是redis的持久化資料。

aof的方式的主要缺點是追加log檔案可能導致體積過大,當系統重啟恢復資料時如果是aof的方式則載入資料會非常慢,幾十g的資料可能需要幾小時才能載入完,當然這個耗時並不是因為磁碟檔案讀取速度慢,而是由於讀取的所有命令都要在記憶體中執行一遍。另外由於每條命令都要寫log,所以使用aof的方式,redis的讀寫效能也會有所下降。

可以考慮將資料儲存到不同的redis例項中,每個例項的記憶體大小在2g左右,避免將雞蛋放到乙個籃子裡,既可以減少快取失效給系統帶來的影響,又可以加快資料恢復的速度,不過同時也給系統設計帶來了一定的複雜性。

redis持久化崩潰問題:

有redis線上運維經驗的人會發現redis在物理記憶體使用比較多,但還沒有超過實際物理記憶體總容量時就會發生不穩定甚至崩潰的 問題,有人認為是基於快照方式持久化的fork系統呼叫造成記憶體占用加倍而導致的,這種觀點是不準確的,因為fork 呼叫的copy-on-write機制是基於作業系統頁這個單位的,也就是只有有寫入的髒頁會被複製,但是一般你的系統不會在短時間內所有的頁都發生了寫 入而導致複製,那麼是什麼原因導致redis崩潰的呢?

答案是redis的持久化使用了buffer io造 成的,所謂buffer io是指redis對持久化檔案的寫入和讀取操作都會使用物理記憶體的page cache,而大多數資料庫系統會使用direct io來繞過這層page cache並自行維護乙個資料的cache,而當redis的持久化檔案過大(尤其是快照檔案),並對其進行讀寫時,磁碟檔案中的資料都會被載入到物理內 存中作為作業系統對該檔案的一層cache,而這層cache的資料與redis記憶體中管理的資料實際是重複儲存的,雖然核心在物理記憶體緊張時會做 page cache的剔除工作,但核心很可能認為某塊page cache更重要,而讓你的程序開始swap ,這時你的系統就會開始出現不穩定或者崩潰了。我們的經驗是當你的redis物理記憶體使用超過記憶體總容量的3/5時就會開始比較危險了。

總結:

1、根據業務需要選擇合適的資料型別,並為不同的應用場景設定相應的緊湊儲存引數。

2、當業務場景不需要資料持久化時,關閉所有的持久化方式可以獲得最佳的效能以及最大的記憶體使用量。

3、如果需要使用持久化,根據是否可以容忍重啟丟失部分資料在快照方式與語句追加方式之間選擇其一,不要使用虛擬記憶體以及diskstore方式。

4、不要讓你的redis所在機器物理記憶體使用超過實際記憶體總量的3/5。

redis.conf中的maxmemory選項,該選項是告訴redis當使用了多少物理記憶體後就開始拒絕後續的寫入請求,該引數能很好的保護好你的redis不會因為使用了過多的物理記憶體而導致swap,最終嚴重影響效能甚至崩潰。

redis.conf檔案中 vm-enabled 為 no

Redis效能調優

向大神學習!儘管redis是乙個非常快速的記憶體資料儲存媒介,也並不代表redis不會產生效能問題。前文中提到過,redis採用單執行緒模型,所有的命令都是由乙個執行緒序列執行的,所以當某個命令執行耗時較長時,會拖慢其後的所有命令,這使得redis對每個任務的執行效率更加敏感。針對redis的效能優...

Redis效能調優

1.估算redis記憶體使用量 以非數字的字串鍵值對為例,假設key和value的長度均為12個位元組,則內部使用的編碼方式為embstr。共計90000個鍵值對占用的空間 redis中儲存鍵值對使用字典,字典內部使用雜湊表陣列,陣列的每個元素dictentry中共有三個指標 指向鍵的指標,指向值的...

Redis 四 高階特性

1 pub sub 發布訂閱 publish 與 subscribe redis 提供了基於發布 訂閱模式的訊息機制,訊息發布者和訂閱者不能直接通訊,客戶端發布訊息的時候指定傳送的頻道,然後訂閱了該頻道的使用者可以接收到該訊息。具體指令如下 1 publish channel message 發布訊...