Redis備忘(二)

 內存回收: redis

       有時候發現10g的Redis刪掉1g的key,內存佔用沒啥變化,由於內存頁分配,有的頁面可能還存在key,整個頁面不能回收。算法

 

 主從同步:數據庫

     CAP原理:一致性 可用性 分區容忍性數組

     redis主從是異步同步數據的,因此並不知足一致性要求(redis是最終一致性),主節點修改後,當即返回,即便主從斷開,主節點依然正常服務,因此知足可用性。緩存

     增量同步:主節點將指令記錄在ringbuffer中,從節點執行同步,並向主節點反饋同步到的偏移量,網絡環境很差時,buffer中的指令會覆蓋,這時候須要快照同步。安全

     快照同步:主庫bgsave將內存數據快照到磁盤,再傳送到從節點,從加載後通知主節點繼續進行增量同步。若是快照時間太長,增量同步的buffer仍是會被覆蓋,網絡

        只能再次快照同步,有可能會快照同步死循環。 因此請務必配置合適的buffer大小。多線程

        單個Redis的內存不宜過大,內存太大會致使 rdb 文件過大,主從全量同步延遲太長app

    Redis無盤複製:dom

         主節點快照同步時,IO太大了,2.8之後能夠快照同步時一邊遍歷內存,一邊經過套接字將數據發送到從節點。

 

 集羣方案:

   1.Sentinel:

            主從方案中無法自動切換主從。由此引入Sentinel集羣

            Sentinel監控主從,若是主掛了自動選擇一個最優的從做爲主,其餘從會和新的主創建主從關係

            客戶端首先鏈接sentinel,經過其找到主節點地址

            主從切換後客戶端會重連新的主,怎麼實現:處理修改性命令的時候捕獲了一個異常 ReadOnlyError,捕獲到後將全部舊鏈接關閉,重連

 

   2.Codis:

           Codis無狀態,能夠部署多個節點。只是簡單將key轉發給服務端,將結果返回客戶端。

           原理:將全部key劃分紅1024個slot,將客戶端傳過來的key作crc32後對1024取模決定存到哪一個slot,slot對應到後面的多個Redis機器之一。 

                     Codis內部維護了Slot和背後機器的映射關係。不一樣Codis實例之間用etcd或zk同步槽位映射關係

                     經過Dashboard 能夠修改槽位信息,當修改後,Codis會監聽到變化並從新同步槽位關係

                     執行mget命令時,Codis會將key分散到多個機器查詢,而後返回歸併結果。

           集羣擴容:若是查詢一個正在遷移的key,Codis會強制該key當即遷移,而後去新機器上查詢(因此value別太大)

  3.Redis Cluster:

         客戶端向一個錯誤的節點發出了指令(即key所在槽位不歸本身管理),該節點會讓客戶端重定向到另外一個節點,客戶端更新本身的槽位映射表

  4.  Redis Stream:

        和Kafka相比,內部沒有partition, 若是想要分區,須要建立多個stream,手動分區

  5.監控:info, monitor , 能夠經過監控異步同步數據失敗次數,據此修改buffer大小

  6.分佈式鎖:

         主節點上申請了鎖,可是忽然主從切換了,鎖還沒來得及同步, 可使用Redlock

         須要提供多個 Redis 實例,這些實例以前相互獨立沒有主從關係,加鎖時,它會向過半節點發送setnx,過半set成功則加鎖成功;

         還須要考慮出錯重試、時鐘漂移等不少細節問題,會形成性能降低。

  7.過時策略:

        同一時間太多的 key 過時,以致於忙不過來?線上指令出現卡頓?

        除了定時遍歷(集中處理)以外,它還會使用惰性策略(零散處理)來刪除過時的key

        1s 10次過時掃描,不會掃描整個過時字典,而是貪心策略:

               1.從過時字典中隨機 20 個 key,刪除過時的

               2.過時的 key 比率超過 1/4,重複步驟1

        若是大批的key同時過時仍是可能線上請求形成卡頓,因此最好給過時時間設置一個隨機範圍。

 

  8. LRU:

       Redis支持maxmemory配置, 超過最大內存後能夠有如下幾種 maxmemory-policy: 

       1. noeviction不可寫庫

       2. volatile-lru:嘗試淘汰設置了過時時間的key,優先淘汰最少使用的

       3. volatile-ttl:跟上面同樣,不過剩餘ttl小的先淘汰

       4. allkeys-lru:淘汰的是全體key,即沒過時也會淘汰

       5. allkeys-random

       6. volatile-random

        Redis爲實現近似 LRU 算法,它給每一個key增長了最後一次被訪問的時間戳。執行寫操做時,發現內存超過maxmemory,執行一次LRU淘汰算法:

      隨機採樣出5個key,淘汰掉最舊的,若是仍是超過maxmemory就繼續隨機採樣淘汰。

 

   9. 刪除優化:

       del刪除的key包含元素過多,也會形成單線程卡頓,4.0引入了unlink 指令,對刪除操做懶處理,丟給後臺線程異步回收內存

  

   10. 數據安全:rename-command flushall ""

   11. 漸進式Rehash: dict結構內部包含兩個hashtable,一般狀況下只有一個hashtable是有值的; 大字典的擴容比較耗時間,Redis單線程很難承受

         遷移數據操做埋伏在當前字典的後續指令中(新的元素掛接到新的數組下面),還會在定時任務中對字典進行主動搬遷。

 

  12. 不要對Redis進行綁核,畢竟還有RDB,AOF這些異步操做

       建議設置swappiness

 

 

  13. 緩存使用的問題:

      緩存穿透:

         1. 返回空:缺點,須要更多內存,若是是攻擊問題更嚴重,能夠設置過時時間

         2. 布隆過濾器

         3. 高可用+降級

         4. 提早演練

     緩存無底洞:FaceBook添加更多memcached節點發現性能更差,由於如mget可能須要訪問n多個節點(hash到不一樣節點)

     更多的節點不表明更高的性能。

     解決:客戶端記住能夠在哪一個節點(其實hash一下就行),對每一個節點的key打包好請求,而後多線程從各個節點mget或pipline

  14.優化:

      1. tcp-backlog

      2. swappiness

 

 

 

   京東訂單的Redis實踐:

     1. 先更新數據庫,再更新緩存

     2. 數據一致性保證:循環5次直到成功,解決網絡抖動形成失敗的機率

                                     還不成功則啓動線程掃描庫,與緩存比較,更新緩存/或發送一條消息到mq,去更新

   網易的Redis技術分享:

      遍歷時間事件鏈表中找到即將觸發的時間,根據這個值去select裏阻塞

相關文章
相關標籤/搜索