基於redis的分佈式緩存disgear開源到github上了

disgear是筆者參考solrcloud架構基於redis實現的分佈式的緩存,支持數據切分到多臺機器上,支持HA,支持讀寫分離和主節點失效自動選舉,目前把它開放到github上,開放給你們node

github:https://github.com/yangbutao/disgeargit

整體設計

 

                                    

                

   

1. 系統需求

1) 性能

內存操做,讀寫性能要求比較高github

2) 數據量

支持數據切分,分爲多個Shard,每一個shard負責必定範圍的數據redis

3) 伸縮性

當單個節點的數據量比較大的時,能夠對該節點進行數據切分,分離成兩部分,增長新的機器便可。算法

4) 可用性

系統不存在單點問題,緩存節點支持HA,master節點宕掉後,自動選舉一個slave爲主節點,對客戶端透明json

2. 設計說明

首先啓動好全部的redis實例,每一個redis實例有一個agent負責監控,agent ping redis實例的狀態,agent 鏈接到zookeeper上建立/collections/collection1/leader_elect/shard1/election下的節點,監控比它小的節點,變化時更新leader節點。api

當agent鏈接zookeeper超時或者agent ping redis實例超時,會刪除zookeeper上的election下的節點(agent ping redis超時,調用zookeeper api刪除節點)。緩存

當ping到redis節點起來後,若檢查到zookeeper上沒有對應節點,則建立相應節點。bash

Leader(master)是緩存負責響應的節點,replica(slave)只負責同步leader的數據,當leader宕機後,提高replica爲主節點。架構

如下是zookeeper上節點的相關說明:

/collections

   |----collection1

        |----leader_elect

               ----shard1[0-7ffffffff]      //節點啓動時,一共須要分幾個 分區,須要聲明該節點屬於哪一個shard

                   ---election         //參與選舉的節點列表,競爭成爲leader節   點,並更新leaders節點列表和clusterstate.json節點內容,並調用腳 本 更改redis的master slave配置

                        ----10.1.1.21

                        ----10.1.1.22

               ----shard2

                   ---eclection

                        ---10.1.1.23

                        ---10.1.1.24

         |---leaders

              ----shard1              //當前shard的leader節點

                  ---10.1.1.21

              -----shard2

                  ----10.1.1.24

/observer                //負責watch collections中節點的變化,

由leader節點更新 clusterstate.json節點的內容,observer節點須要在系統初始 化過程當中最新選舉出leader節點,作watch collections下的 節點的變化。

     |---election          //其下是供選擇的節點

     |----leader           //這樣一個好處是每一個client節點無需對多個zookeeper的節點監控計算,由單獨的節點對這些變化的節點作監控, 來更新集羣狀態,這樣每一個client只須要 watch 集羣狀態 內容zookeeper節點便可。

/live_nodes

    |---10.1.1.21

    |----10.1.1.22

    |----10.1.1.23

    |-----10.1.1.24

/clusterstate.json                      //集羣狀態,當有節點變化時,更新這個節點 內容,每一個client端監聽該節點內容的變化, 緩存在本地cache中。

相關內容以下:

{collection1={

  "shards":{

    "shard1":{

      "range":"80000000-ffffffff",

       「leader」:node1,

      "replicas":{

        "node1":{

          "state":"alive",         "node_name":"192.168.1.21:8983"},

        "node2":{

          "state":"alive",

            "node_name":"192.168.1.22:8983"

          }}},

 "shard2":{

      "range":"0-7fffffff",

      "state":"active",

       「leader」:node3,

      "replicas":{

        "node3":{

         "node_name":"192.168.1.23:8983"},

        "core_node4":{

           "node_name":"192.168.1.24:8983"

          }}},

 

模塊設計說明 

1. 數據切分、節點擴容、key hash

對於數據切分,數據的範圍取Integer.MIN_VALUE, Integer.MAX_VALUE,首次初始化時,根據規劃的Shard的數量,平均進行切分,每一個Shard負責一個固定的數據範圍,好比Shard1[0-7fffffff],這些Shard和數據的範圍會持久化到zookeeper節點上,以便於集羣重啓後,從zookeeper本地拉起Shard劃分和數據範圍的相關數據,以下圖所示。

/collections

   |----collection1

        |----leader_elect

               ----shard1[0-7ffffffff] 

               ----shard2[800000-9ffffffff]

當須要擴容緩存節點時,管理員能夠對Shard進行split操做,生成兩個新的Shard,每一個Shard負責一部分數據,註冊在zooleeper上的/collections/collection1/leader_elect節點下。好比Shard1[0-7ffffffff]通過split操做後,變成Shard1_1[0-3ffffffff]和Shard1_2[400000-7fffffffff]。

/collections

   |----collection1

        |----leader_elect

               ----shard1[0-7ffffffff] 

               ----shard2[800000-9ffffffff]

                   ----shard1_1[0-3ffffffff] 

                   ----shard1_2[0-3ffffffff]

  新的節點加入到新的Shard分區中,完成leader選舉等一系列操做後,更新集羣拓撲狀態,並刪除老的Shard分區,這樣新的Shard就處於可用狀態。

對於key的hash定位,採用murmurhash3_x86_32 算法,效率比較高,而後判斷該hash值落在哪一個shard的數據範圍內,進行數據的分區定位。

2. 緩存代理Agent

Agent做爲緩存節點的代理,一方面和zookeeper進行通訊,把緩存節點的狀態通知給zookeeper,另一方面對redis緩存節點作管理和監控。

1) Agent檢測redis節點是否存活:

須要在Agent中調用如下腳本(monitor_redis.sh),把返回的結果,通知給zookeeper

ALIVE=$(/opt/cache/redis-2.6.16/src/redis-cli -h 10.1.1.25 -p 6379 -a 123 PING)

echo $ALIVE

2) 變動爲master節點

當節點上的agent在zookeeper上成爲leader節點時,須要通知agent把它代理的redis變動爲master節點,agent調用如下腳本。

主節點的腳本(redis_master.sh):

#!/bin/bash

/opt/cache/redis-2.6.16/src/redis-cli -h 10.1.1.26 -p 6379 slaveof NO ONE   

3) 變動爲slave節點

當節點上的agent在zookeeper上成爲replica節點時,須要通知agent把它代理的redis變動爲slave節點,agent調用如下腳本。

slave節點腳本(redis_slaves.sh):

#!/bin/bash

/opt/cache/redis-2.6.16/src/redis-cli -h 10.1.1.26 -p 6379 slaveof 10.1.1.25 6379 

3. 集羣狀態觀察者Observer

Observer負責對整個集羣collection下的Shard節點的變更進行監聽,更新zookeeper上的集羣狀態節點cloudstate.json。

Agent節點在啓動過程當中,首選要作的就是Observer的選舉。

Observer須要由zookeeper選舉出來後,監聽collections下節點的變化,如有變化則進行處理process,計算的結果設置到zookeeper的cloudstate.json節點。

當cloudstate.json節點數據變化時,負責監聽該節點的全部客戶端都更新本地客戶端內存。

/observer                

     |---election          

          ----10.1.1.21

          ----10.1.1.22

         -----10.1.1.23

     |----leader         

           -----10.1.1.22      

4. Shard leader選舉

Shard節點在zookeeper上建立完成後,緩存節點在啓動的過程當中,須要經過命令行-D參數或者配置文件的形式加入到集羣中的某一個Shard分區下,參與leader的選舉,具體實現是爲每一個節點生成一個數字,每一個節點只須要監控比本身小的節點便可,若有變化,則進行通知,並使得數字最小的節點成爲leader節點。

/collections

   |----collection1

        |----leader_elect

               ----shard1               //節點啓動時,一共須要分幾個分區,須要 聲明該節點屬於哪一個shard

                   ---eclection         //參與選舉的節點列表,競爭成爲leader節   點,並更新leaders節點列表和clusterstate.json節點內容,並調用腳 本 更改redis的master slave配置

                        ----10.1.1.21

                        ----10.1.1.22

               ----shard2

                   ---eclection

                        ---10.1.1.23

                        ---10.1.1.24

         |---leaders

              ----shard1              //當前shard的leader節點

                  ---10.1.1.21

              -----shard2

                  ----10.1.1.24

 

5. 緩存節點的擴容

當某shard的訪問壓力過大或者數據量比較大時候,節點的擴展有兩種方式,

一種是增長shard中的節點數量,提升讀的能力,這種方式已經實現;

另一種方式對壓力大的shard作split的操做,一個shard分割爲兩個shard,提升shard的寫數據的能力,這種節點的擴展方式目前還不支持,已歸入到後續的計劃中。

使用說明

Agent的啓動腳本:

MAIN="com.newcosoft.cache.agent.AgentMain"
$JAVA $JAVA_OPTS  -cp "$CLASSPATH" $JVMFLAGS $MAIN  -Dcol=col1 -Dshard=shard1 -Dnode=node25 \
  -DbaseUrl=10.1.1.25:6379 -DscriptPath=/opt/lsmp -DshardNum=3 -Dzk_url=10.1.1.25:2181

其中-Dcol表示當前建立的collection名稱,對於redis來說,表明要存儲庫的邏輯名稱

-Dshard表示當前的節點的shard名稱

-Dnode表示當前節點的邏輯名稱

-DbaseUrl表示redis的主機IP和端口號

-DscriptPath表示redis監控和操做相關的腳本的路徑,腳本有monitor_redis.sh、redis_master.sh、redis_slaves.sh

-DshardNum表示當前collection中的shard數目

-Dzk_url表明zookeeper集羣的地址

 

Client端的使用:

在使用disgear的client端啓動初始化中,引用disgear相關的jar,並調用

com.newcosoft.client.ClusterStateCacheManager.INSTANCE=new ClusterStateCacheManager(zkUrl);

ClusterStateCacheManager.INSTANCE.createClusterStateWatcher();

建立clusterState的監聽器。

這樣後續經過com.newcosoft.client.ClusterStateCacheManager.INSTANCE.getClusterState()就能夠得到當前集羣的節點狀態,

進而選擇合適的節點進行分發數據存取請求。

相關文章
相關標籤/搜索