一、說明
redis 3.0叢集功能出來已經有一段時間了,目前最新穩定版是3.0.5,我了解到已經有很多網際網路公司在生産環境使用,比如唯品會、美團等等,剛好公司有個新項目,預估的量單機redis無法滿足,開發又不想在代碼層面做拆分,是以就推薦他們嘗試一下redis叢集,下面做了一些相關筆記,以備後用
二、環境
1、redis節點
1
2
3
<code>10.10.2.70:6300 10.10.2.70:6301 主從</code>
<code>10.10.2.71:6300 10.10.2.71:6301 主從</code>
<code>10.10.2.85:6300 10.10.2.85:6301 主從</code>
2、redis版本
<code>redis version 3.0.5</code>
三、安裝配置
1、安裝redis
4
5
6
7
8
<code>wget http:</code><code>//download</code><code>.redis.io</code><code>/releases/redis-3</code><code>.0.5.</code><code>tar</code><code>.gz</code>
<code>tar</code> <code>-zxvf redis-3.0.5.</code><code>tar</code><code>.gz</code>
<code>cd</code> <code>redis-3.0.5</code>
<code>make</code>
<code>cp</code> <code>redis-3.0.5</code><code>/src/redis-trib</code><code>.rb </code><code>/bin/</code>
<code>cp</code> <code>redis-3.0.5</code><code>/src/redis-server</code> <code>/bin/</code>
<code>cp</code> <code>redis-3.0.5</code><code>/src/redis-cli</code> <code>/bin/</code>
2、安裝ruby及ruby的redis子產品
<code>yum -y </code><code>install</code> <code>ruby rubygems</code>
<code>gem </code><code>install</code> <code>redis --version 3.0.5</code>
3、核心調優
<code>echo</code> <code>never > </code><code>/sys/kernel/mm/transparent_hugepage/enabled</code>
<code>echo</code> <code>"vm.overcommit_memory = 1"</code> <code>>> </code><code>/etc/sysctl</code><code>.conf </code>
<code>sysctl -p</code>
4、建立目錄
<code>mkdir</code> <code>/data/redis/6300</code> <code>-p</code>
<code>mkdir</code> <code>/data/redis/6301</code>
5、撰寫redis配置檔案(cp配置檔案注意修改端口)
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<code>vim </code><code>/etc/redis_6300</code><code>.conf</code>
<code>daemonize </code><code>yes</code>
<code>port 6300</code>
<code>tcp-backlog 511</code>
<code>timeout 0</code>
<code>tcp-keepalive 0</code>
<code>loglevel notice</code>
<code>maxmemory 10gb</code>
<code>databases 16</code>
<code>dir</code> <code>/data/redis/6300</code>
<code>slave-serve-stale-data </code><code>yes</code>
<code>logfile </code><code>"/data/redis/6300/redis_6300.log"</code>
<code>#slave隻讀</code>
<code>slave-</code><code>read</code><code>-only </code><code>yes</code>
<code>#not use default</code>
<code>repl-disable-tcp-nodelay </code><code>yes</code>
<code>slave-priority 100</code>
<code>#打開aof持久化</code>
<code>appendonly </code><code>yes</code>
<code>#每秒一次aof寫</code>
<code>appendfsync everysec</code>
<code>#關閉在aof rewrite的時候對新的寫操作進行fsync</code>
<code>no-appendfsync-on-rewrite </code><code>yes</code>
<code>auto-aof-rewrite-min-size 64mb</code>
<code>lua-</code><code>time</code><code>-limit 5000</code>
<code>#打開redis叢集</code>
<code>cluster-enabled </code><code>yes</code>
<code>cluster-config-</code><code>file</code> <code>/data/redis/6300/nodes-6300</code><code>.conf</code>
<code>#節點互連逾時的閥值(機關毫秒)</code>
<code>cluster-node-timeout 15000</code>
<code>#一個主節點在擁有多少個好的從節點的時候就要割讓一個從節點出來給其他沒有從節點或者從節點挂掉的主節點</code>
<code>cluster-migration-barrier 1</code>
<code>#如果某一些key space沒有被叢集中任何節點覆寫,最常見的就是一個node挂掉,叢集将停止接受寫入</code>
<code>cluster-require-full-coverage no</code>
<code>#部署在同一機器的redis執行個體,把auto-aof-rewrite搓開,防止瞬間fork所有redis程序做rewrite,占用大量記憶體</code>
<code>auto-aof-rewrite-percentage 80-100</code>
<code>slowlog-log-slower-than 10000</code>
<code>slowlog-max-len 128</code>
<code>notify-keyspace-events </code><code>""</code>
<code>hash</code><code>-max-ziplist-entries 512</code>
<code>hash</code><code>-max-ziplist-value 64</code>
<code>list-max-ziplist-entries 512</code>
<code>list-max-ziplist-value 64</code>
<code>set</code><code>-max-intset-entries 512</code>
<code>zset-max-ziplist-entries 128</code>
<code>zset-max-ziplist-value 64</code>
<code>activerehashing </code><code>yes</code>
<code>client-output-buffer-limit normal 0 0 0</code>
<code>client-output-buffer-limit slave 256mb 64mb 60</code>
<code>client-output-buffer-limit pubsub 32mb 8mb 60</code>
<code>hz 10</code>
<code>aof-rewrite-incremental-fsync </code><code>yes</code>
6、啟動服務
<code>redis-server </code><code>/etc/redis_6300</code><code>.conf</code>
<code>redis-server </code><code>/etc/redis_6301</code><code>.conf</code>
<code>echo</code> <code>"redis-server /etc/redis_6300.conf"</code> <code>>> </code><code>/etc/rc</code><code>.</code><code>local</code>
<code>echo</code> <code>"redis-server /etc/redis_6301.conf"</code> <code>>> </code><code>/etc/rc</code><code>.</code><code>local</code>
7、初始化叢集
<code>#節點角色由順序決定,先master之後是slave,本文中6300是master,6301是slave</code>
<code>redis-trib.rb create --replicas 1 10.10.2.70:6300 10.10.2.71:6300 10.10.2.85:6300 10.10.2.70:6301 10.10.2.71:6301 10.10.2.85:6301</code>
8、檢視叢集狀态
<code>redis-trib.rb check 10.10.2.70:6300</code>
ps:
redis-trib.rb是一個ruby工具,封裝了redis叢集的一些指令,用這個工具操作叢集非常友善,比如上面初始化叢集,檢視叢集狀态,還有添加、删除節點,遷移slot等等功能
四、redis叢集維護
a、場景1
線上的叢集已經有瓶頸,叢集需要擴容,比如我們已經準備了一主一從(10.10.2.85:6302、10.10.2.85:6303),如下:
1、添加一個主節點
<code>[root@yw_0_0 ~]</code><code># redis-trib.rb add-node 10.10.2.85:6302 10.10.2.70:6300</code>
<code>>>> adding node 10.10.2.85:6302 to cluster 10.10.2.70:6300</code>
<code>connecting to node 10.10.2.70:6300: ok</code>
<code>connecting to node 10.10.2.85:6300: ok</code>
<code>connecting to node 10.10.2.85:6301: ok</code>
<code>connecting to node 10.10.2.71:6300: ok</code>
<code>connecting to node 10.10.2.70:6301: ok</code>
<code>connecting to node 10.10.2.71:6301: ok</code>
<code>>>> performing cluster check (using node 10.10.2.70:6300)</code>
<code>s: cd1f2c1f348bb4359337e7462c1e21dc82f1551b 10.10.2.70:6300</code>
<code> </code><code>slots: (0 slots) slave</code>
<code> </code><code>replicates 85412cf3d8e69354115fc0991f470b32b9213cd7</code>
<code>m: 6bea6afa2ee8dfb0cc3c96f804eb3fa77ce98013 10.10.2.85:6300</code>
<code> </code><code>slots:0-5460 (5461 slots) master</code>
<code> </code><code>1 additional replica(s)</code>
<code>s: a74642c0fbc98f921be477eabcdd22eccd89891f 10.10.2.85:6301</code>
<code> </code><code>replicates 2568dbd91fffa16ff93ea8db19275fd7ec8af41a</code>
<code>m: 2568dbd91fffa16ff93ea8db19275fd7ec8af41a 10.10.2.71:6300</code>
<code> </code><code>slots:5461-10922 (5462 slots) master</code>
<code>m: 85412cf3d8e69354115fc0991f470b32b9213cd7 10.10.2.70:6301</code>
<code> </code><code>slots:10923-16383 (5461 slots) master</code>
<code>s: 22d2dec483824b84571a60e8c037fff957615552 10.10.2.71:6301</code>
<code> </code><code>replicates 6bea6afa2ee8dfb0cc3c96f804eb3fa77ce98013</code>
<code>[ok] all nodes agree about slots configuration.</code>
<code>>>> check </code><code>for</code> <code>open</code> <code>slots...</code>
<code>>>> check slots coverage...</code>
<code>[ok] all 16384 slots covered.</code>
<code>connecting to node 10.10.2.85:6302: ok</code>
<code>>>> send cluster meet to node 10.10.2.85:6302 to </code><code>make</code> <code>it </code><code>join</code> <code>the cluster.</code>
<code>[ok] new node added correctly.</code>
10.10.2.85:6302是要加的新節點,10.10.2.70:6300是叢集中已存在的任意節點
2、給主節點添加從節點
<code>[root@yw_0_0 ~]</code><code># redis-trib.rb add-node --slave --master-id 5ef18f95f75756891aa948ea1f200044f1d3947c 10.10.2.85:6303 10.10.2.70:6300</code>
<code>>>> adding node 10.10.2.85:6303 to cluster 10.10.2.70:6300</code>
<code>m: 5ef18f95f75756891aa948ea1f200044f1d3947c 10.10.2.85:6302</code>
<code> </code><code>slots: (0 slots) master</code>
<code> </code><code>0 additional replica(s)</code>
<code>connecting to node 10.10.2.85:6303: ok</code>
<code>>>> send cluster meet to node 10.10.2.85:6303 to </code><code>make</code> <code>it </code><code>join</code> <code>the cluster.</code>
<code>waiting </code><code>for</code> <code>the cluster to </code><code>join</code><code>.</code>
<code>>>> configure node as replica of 10.10.2.85:6302.</code>
--slave 指定要加的是從節點,--master-id 指定這個從節點的主節點id,10.10.2.85:6303是需要新加的從節點,10.10.2.70:6300是叢集已存在的任意節點
3、遷移一些slot給新節點
<code>[root@yw_0_0 ~]</code><code># redis-trib.rb reshard 10.10.2.70:6300</code>
<code>s: fc90d090fae909fd4f962752941c039d081d3854 10.10.2.85:6303</code>
<code> </code><code>replicates 5ef18f95f75756891aa948ea1f200044f1d3947c</code>
<code>how many slots </code><code>do</code> <code>you want to move (from 1 to 16384)? 3000 </code><code>#設定需要把3000個slot做移動</code>
<code>what is the receiving node id? 5ef18f95f75756891aa948ea1f200044f1d3947c </code><code>#設定接收這3000個slot的節點id,也就是剛才新加的10.10.2.85:6302的id</code>
<code>please enter all the </code><code>source</code> <code>node ids.</code>
<code> </code><code>type </code><code>'all'</code> <code>to use all the nodes as </code><code>source</code> <code>nodes </code><code>for</code> <code>the </code><code>hash</code> <code>slots.</code>
<code> </code><code>type </code><code>'done'</code> <code>once you entered all the </code><code>source</code> <code>nodes ids.</code>
<code>source node </code><code>#1:85412cf3d8e69354115fc0991f470b32b9213cd7 #設定這3000slot的來源id,這裡我從叢集之前的3個節點分别去取一部分slot</code>
<code>source node </code><code>#2:6bea6afa2ee8dfb0cc3c96f804eb3fa77ce98013 #設定這3000slot的來源id,這裡我從叢集之前的3個節點分别去取一部分slot</code>
<code>source node </code><code>#3:2568dbd91fffa16ff93ea8db19275fd7ec8af41a #設定這3000slot的來源id,這裡我從叢集之前的3個節點分别去取一部分slot</code>
<code>source node </code><code>#4:done #輸入done開始做一些初始化操作</code>
<code>此處省略</code>
<code>do you want to proceed with the proposed reshard plan (</code><code>yes</code><code>/no</code><code>)? </code><code>yes</code> <code>輸入</code><code>yes</code><code>确認開始遷移slot</code>
b、場景二
上面的例子是叢集擴容,相對的,由于各種原因叢集可能也需要縮容,下面的例子把上文擴容的節點下線,步驟如下:
1、遷移這個節點的slot到其他節點(有slot的節點是不可以直接下線的)
<code> </code><code>slots:999-5460 (4462 slots) master</code>
<code> </code><code>slots:0-998,5461-6461,10923-11921 (2999 slots) master</code>
<code> </code><code>slots:6462-10922 (4461 slots) master</code>
<code> </code><code>slots:11922-16383 (4462 slots) master</code>
<code>how many slots </code><code>do</code> <code>you want to move (from 1 to 16384)? 3000 </code><code>#上文給這個節點遷入了3000個slot,是以這裡還選擇遷出3000個slot</code>
<code>what is the receiving node id? 85412cf3d8e69354115fc0991f470b32b9213cd7 </code><code>#接收這3000slot節點的主id</code>
<code>source node </code><code>#1:5ef18f95f75756891aa948ea1f200044f1d3947c #要下線節點的主id</code>
<code>source node </code><code>#4:done</code>
<code>do you want to proceed with the proposed reshard plan (</code><code>yes</code><code>/no</code><code>)?</code><code>yes</code>
2、然後檢視10.10.2.85:6302這個maser上已經沒有slot了
<code>10.10.2.71:6300> cluster nodes</code>
<code>85412cf3d8e69354115fc0991f470b32b9213cd7 10.10.2.70:6301 master - 0 1445853133399 12 connected 0-999 6462-7460 10923-16383</code>
<code>22d2dec483824b84571a60e8c037fff957615552 10.10.2.71:6301 slave 6bea6afa2ee8dfb0cc3c96f804eb3fa77ce98013 0 1445853132898 10 connected</code>
<code>6bea6afa2ee8dfb0cc3c96f804eb3fa77ce98013 10.10.2.85:6300 master - 0 1445853134400 10 connected 1000-5461</code>
<code>2568dbd91fffa16ff93ea8db19275fd7ec8af41a 10.10.2.71:6300 myself,master - 0 0 11 connected 5462-6461 7461-10922</code>
<code>cd1f2c1f348bb4359337e7462c1e21dc82f1551b 10.10.2.70:6300 slave 85412cf3d8e69354115fc0991f470b32b9213cd7 0 1445853131395 12 connected</code>
<code>fc90d090fae909fd4f962752941c039d081d3854 10.10.2.85:6303 slave 5ef18f95f75756891aa948ea1f200044f1d3947c 0 1445853133899 8 connected</code>
<code>a74642c0fbc98f921be477eabcdd22eccd89891f 10.10.2.85:6301 slave 2568dbd91fffa16ff93ea8db19275fd7ec8af41a 0 1445853129394 11 connected</code>
<code>5ef18f95f75756891aa948ea1f200044f1d3947c 10.10.2.85:6302 master - 0 1445853132397 8 connected</code>
3、下線slave節點
<code>[root@yw_0_0 ~]</code><code># redis-trib.rb del-node 10.10.2.85:6303 fc90d090fae909fd4f962752941c039d081d3854</code>
<code>>>> removing node fc90d090fae909fd4f962752941c039d081d3854 from cluster 10.10.2.85:6303</code>
<code>>>> sending cluster forget messages to the cluster...</code>
<code>>>> shutdown the node.</code>
4、下線master節點
<code>redis-trib.rb del-node 10.10.2.70:6301 5ef18f95f75756891aa948ea1f200044f1d3947c</code>
<code>>>> removing node 5ef18f95f75756891aa948ea1f200044f1d3947c from cluster 10.10.2.70:6301</code>
c、場景三
叢集中一個節點的master挂掉,從節點提升為主節點,還沒有來的急給這個新的主節點加從節點,這個新的主節點就又挂掉了,那麼叢集中這個節點就徹底不可以用了,為了解決這個問題,我們至少保證每個節點的maser下面有兩個以上的從節點,這樣一來,需要的記憶體資源或者伺服器資源就翻倍了,有沒有一個折中的方法呢,答案是肯定的,還節點上文配置檔案中的cluster-migration-barrier參數不,我們隻需要給叢集中其中一個節點的master挂多個從庫,當其他節點的master下沒有可用的從庫時,有多個從庫的master會割讓一個slave給他,保證整個叢集的可用性
1、給10.10.2.70:6300 10.10.2.70:6301 這組節點下面加一個從庫10.10.2.85:6302
<code>[root@yw_0_0 ~]</code><code># redis-trib.rb add-node --slave --master-id cd1f2c1f348bb4359337e7462c1e21dc82f1551b 10.10.2.85:6302 10.10.2.70:6300</code>
<code>m: cd1f2c1f348bb4359337e7462c1e21dc82f1551b 10.10.2.70:6300</code>
<code> </code><code>slots:3000-5461,6462-7460,10923-16383 (8922 slots) master</code>
<code>m: e36cdef7a26ed59e8d9db2cf1dbc1997bfc9dfde 10.10.2.85:6300</code>
<code> </code><code>slots:0-2999 (3000 slots) master</code>
<code> </code><code>slots:5462-6461,7461-10922 (4462 slots) master</code>
<code>s: 85412cf3d8e69354115fc0991f470b32b9213cd7 10.10.2.70:6301</code>
<code> </code><code>replicates cd1f2c1f348bb4359337e7462c1e21dc82f1551b</code>
<code>s: 89fcc4994a99ed2fe9bbb908c58dfda2cf31e7d2 10.10.2.85:6301</code>
<code> </code><code>replicates e36cdef7a26ed59e8d9db2cf1dbc1997bfc9dfde</code>
<code>s: 1f3ea36eacbe005a4b9ac52aeef6d83337dac051 10.10.2.71:6301</code>
<code>>>> configure node as replica of 10.10.2.70:6300.</code>
2、把10.10.2.71:6300 10.10.2.71:6301這組的從節點停掉
<code>redis-cli -h 10.10.2.71 -p 6301 </code><code>shutdown</code>
3、檢視10.10.2.85:6302這個節點是否成為10.10.2.71:6300的從庫
<code>85412cf3d8e69354115fc0991f470b32b9213cd7 10.10.2.70:6301 slave cd1f2c1f348bb4359337e7462c1e21dc82f1551b 0 1445911596844 17 connected</code>
<code>89fcc4994a99ed2fe9bbb908c58dfda2cf31e7d2 10.10.2.85:6301 slave e36cdef7a26ed59e8d9db2cf1dbc1997bfc9dfde 0 1445911594841 20 connected</code>
<code>cd1f2c1f348bb4359337e7462c1e21dc82f1551b 10.10.2.70:6300 master - 0 1445911593839 17 connected 3000-5461 6462-7460 10923-16383</code>
<code>2b34532cd6937063d1da26cd4652881b73d97a06 10.10.2.85:6302 slave 2568dbd91fffa16ff93ea8db19275fd7ec8af41a 0 1445911592838 17 connected </code><code>#已成功挂到了10.10.2.71:6300下</code>
<code>1f3ea36eacbe005a4b9ac52aeef6d83337dac051 10.10.2.71:6301 slave,fail 2568dbd91fffa16ff93ea8db19275fd7ec8af41a 1445911561982 1445911559778 11 disconnected</code>
<code>e36cdef7a26ed59e8d9db2cf1dbc1997bfc9dfde 10.10.2.85:6300 master - 0 1445911595843 20 connected 0-2999</code>
五、cluster相關指令
<code>叢集</code>
<code>cluster info 列印叢集的資訊</code>
<code>cluster nodes 列出叢集目前已知的所有節點(node),以及這些節點的相關資訊。</code>
<code>節點</code>
<code>cluster meet <ip> <port> 将 ip 和 port 所指定的節點添加到叢集當中,讓它成為叢集的一份子。</code>
<code>cluster forget <node_id> 從叢集中移除 node_id 指定的節點。</code>
<code>cluster replicate <node_id> 将目前節點設定為 node_id 指定的節點的從節點。</code>
<code>cluster saveconfig 将節點的配置檔案儲存到硬碟裡面。</code>
<code>槽(slot)</code>
<code>cluster addslots <slot> [slot ...] 将一個或多個槽(slot)指派(assign)給目前節點。</code>
<code>cluster delslots <slot> [slot ...] 移除一個或多個槽對目前節點的指派。</code>
<code>cluster flushslots 移除指派給目前節點的所有槽,讓目前節點變成一個沒有指派任何槽的節點。</code>
<code>cluster setslot <slot> node <node_id> 将槽 slot 指派給 node_id 指定的節點,如果槽已經指派給另一個節點,那麼先讓另一個節點删除該槽>,然後再進行指派。</code>
<code>cluster setslot <slot> migrating <node_id> 将本節點的槽 slot 遷移到 node_id 指定的節點中。</code>
<code>cluster setslot <slot> importing <node_id> 從 node_id 指定的節點中導入槽 slot 到本節點。</code>
<code>cluster setslot <slot> stable 取消對槽 slot 的導入(</code><code>import</code><code>)或者遷移(migrate)。</code>
<code>鍵</code>
<code>cluster keyslot <key> 計算鍵 key 應該被放置在哪個槽上。</code>
<code>cluster countkeysinslot <slot> 傳回槽 slot 目前包含的鍵值對數量。</code>
<code>cluster getkeysinslot <slot> <count> 傳回 count 個 slot 槽中的鍵。</code>
參考文章:
<a href="http://redisdoc.com/topic/cluster-tutorial.html" target="_blank">http://redisdoc.com/topic/cluster-tutorial.html</a>