Redis 集群擴容

er74 9年前發布 | 31K 次閱讀 Redis NoSQL數據庫

 

幾乎每一個網站都需要用戶登錄狀態系統,其中核心是存儲 Session 的用戶登錄狀態存儲系統。 主流的實現之一是使用 Redis 存儲用戶登錄信息,Redis 特點是功能簡單、無依賴、 存儲結構豐富、有持久化功能。 我大堆糖的 Session 存儲系統也正是基于 Redis。

可是 Redis 也存在一些問題,比如 Redis 自身沒有 Sharding 功能,Replication 也是在逐步完善完善過程中 (2.4 支持Replication,2.8 加入Replication partial resynchronization功能)。 縱觀當下流行的 DB 系統,哪個不是自帶這兩個特性,這兩個分布式特性應該成為新出產的 DB 系統的標配。 而且作者還經常發布延期,放煙霧彈,不知道 Redis 自帶 Sharding 特性要等到何年馬月。

隨著業務規模的擴大,單臺 Redis 實例不能滿足需求。 考慮到 Redis 也是久經考驗的戰士,替換掉他成本比較高,那就對 Redis 進行擴容。

擴容的基本要求是:

  • 擴大系統容量,成為分布式系統,未來有橫向擴展
  • 業務不中斷
  • 保證原始數據的可用性
  • </ul>

    Google 了一下,有兩個項目可以參考: https://github.com/idning/redis-mgr 和豌豆莢的 Codis

    研究了這兩項目的代碼之后,發現前者存在幾個問題: 需要停機進行操作。 后者提供了完整一套解決方案,Server/Proxy/Config Manage,對我這次遷移來說,太重了, 而且項目比較新,風險高,只能用來參考實現方法。

    最后我決定參考 redis-mgr 的方案,然后使用兩種方式同步數據: 系統運行中打上 patch 完成數據的動態遷移;后臺跑遷移數據腳本。

    方案的關鍵詞

    dump/restore/pttl

    核心的操作流程是: 使用dump命令導出數據,restore命令恢復數據,pttl命令獲取設置 TTL。

    Presharding

    Redis 官方沒有 sharding 方案,但提供一種策略 presharding。 Redis 作者寫了一篇 Redis Presharding 。核心是: 提前做 2^n 個實例,避免擴容時候數據遷移,一般使用 2^n 個實例, 目的是為了能夠自然地乘以 2 進行拆分。 這些實例可以分開放,也可以放在同一臺機器上面。

    我這次操作,將OLD_CLUSTER的一個實例拆分為了NEW_CLUSTER的 32 個實例, 跑在 4 臺服務器上面。

    Twemproxy

    Redis 的 經典款 Proxy,用來實現對多個 Redis 實例 sharding, 推ter 出品, 鏈接

    一致性 Hash

    傳統的 Hash 方法是hash(key) = value % nodes.length, 當加入、減少 Hash 節點時候,會導致hash(key)的全部失效。 典型的一致性 Hash 算法, Ketama 通過環狀 node 分布,解決了這個問題。

    Twemproxy 還提供modula和 random 兩種分布式方案。

    db 大小預估

    Redis 只能查看整個實例內存尺寸。不能查看單個 db。 使用ramdomkey做抽樣檢查,取 1% key 抽樣,估計單個 key 大小, 然后做 benchmark 估算操作性能,估算操作時間。

    動態遷移數據

    為了在遷移過程中保證服務可用,需要將數據兼容 Redis 集群OLD_CLUSTER/NEW_CLUSTER, 業務代碼必須同時支持訪問兩個集群,做法也很簡單

    • 訪問NEW_CLUSTER
    • 有數據則繼續操作,無數據則訪問OLD_CLUSTER,獲取數據DATA
    • 將數據和 TTL 保存到NEW_CLUSTER
    • </ul>

      將這個邏輯封裝成一個 client,替換掉原來 Redis Client 即可。

      注意,這個點可能產生幻讀,讀取 key 和寫入 key 有個時間差, 但是我處理的 session 是 immutable 數據,不會出現問題。 而如果將 Redis 用作 Persistence,就要評估對業務的影響了。

      后臺遷移數據

      依賴用戶訪問來進行遷移,效率太低了,這個遷移時間和最長 TTL 時間相當, 需要主動將這個數據從OLD_CLUSTER遷移到NEW_CLUSTER。

      方案也很簡單,使用randomkey獲取一批數據,然后按動態遷移數據方法進行遷移。

      pipeline

      如果在業務邏輯中使用了 PIPELINE,就會遇到問題,需要改寫掉業務方案, 待遷移完成之后,再進行恢復。

      multikey

      mget/mset等多鍵操作方法需要注意拆解 key,然后一一dump/restore/ttl。

      正式操作

      線上操作的數據:

      # 0.483 g db0
      12:05:19,444 - main - INFO - v, dumps keys 1014/1375371/..., time: 974.183676004

      4.552 g db1

      17:38:36,422 - main - INFO - v, dumps keys 1392/7711834/..., time: 3076.41647506</pre>

 本文由用戶 er74 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!