一、為什么要弄redis集群
集群技術是構建高性能網站架構的重要手段,試想在網站承受高并發訪問壓力的同時,還需要從海量數據中查詢出滿足條件的數據,并快速響應,我們必然想到的是將數據進行切片,把數據根據某種規則放入多個不同的服務器節點,來降低單節點服務器的壓力。上篇redis_主從我們講到了 Redis 的主從復制技術,當實現了多節點的 master-slave 后,我們也可以把它叫做集群,但我們今天要講的集群主要是利用切片技術來組建的集群。我們最后希望達到的是類似下圖:
二、實現策略
因為從3.0開始以后官方已經支持了 redis cluster,https://redis.io/topics/cluster-tutorial
集群要實現的目的是要將不同的 key 分散放置到不同的 redis 節點,這里我們需要一個規則或者算法,通常的做法是獲取 key 的哈希值,然后根據節點數來求模,但這種做法有其明顯的弊端,當我們需要增加或減少一個節點時,會造成大量的 key 無法命中,這種比例是相當高的,所以就有人提出了一致性哈希的概念。
由于官方版本是基于哈希槽(hash slot)的概念來實現的,我們還是從其官方介紹中翻譯解釋一下:
Redis 集群中內置了 16384 個哈希槽,當需要在 Redis 集群中放置一個 key-value 時,redis 先對 key 使用 crc16 算法算出一個結果,然后把結果對 16384 求余數,這樣每個 key 都會對應一個編號在 0-16383 之間的哈希槽,redis 會根據節點數量大致均等的將哈希槽映射到不同的節點。
使用哈希槽的好處就在于可以方便的添加或移除節點:
當需要增加節點時,只需要把其他節點的某些哈希槽挪到新節點就可以了;
當需要移除節點時,只需要把移除節點上的哈希槽挪到其他節點就行了;
三、集群實現
對于我們來說,在新增或移除節點的能做到無縫(即不需要重啟集群),這點它做到了。還是來看看具體的實現吧:
新建redis_cluster文件夾下面新建6000、6100、6200三個文件夾。
把src 目錄下面的redis-server、redis.conf這兩個文件分別拷貝到這三個目錄里面,拷貝完之后就像這樣子了:
[mysql@localhost 6000]$ ll -rw-rw-r--. 1 mysql mysql 116 Aug 21 05:37 redis.conf -rwxrwxr-x. 1 mysql mysql 7820101 Aug 21 05:29 redis-server
修改每個目錄下面的redis.conf文件因為我們啟動的端口是不一樣的,vi redis.conf刪除里面的所有添加如下的:
daemonize yes //指定以守護進程啟動 port 6000 //啟動端口 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes
依次啟動每一個實例文件夾下面的./redis-server ./redis.conf,這樣的話3個實例就啟動了,但是如何將3個實例維護成一個集群呢,在src目錄下面執行:
./redis-trib.rb create --replicas 0 127.0.0.1:6000 127.0.0.1:6100 127.0.0.1:6200
執行以后是不是會發現執行失敗提示沒有redis-trib.rb文件,好吧我們還忘了裝一個,因為我們執行的是ruby命令,所以還需要安裝ruby:
https://rubygems.org/gems/redis下載,然后離線安裝。sudo gem install redis-3.3.1.gem --local
安裝完成以后再src目錄下面就有了redis-trib.rb文件。
執行上面的集群命令控制臺輸出如下:
來試試集群的效果吧:
在6000端口實例上測試 [mysql@localhost src]$ ./redis-cli -c -p 6000 127.0.0.1:6000> get name -> Redirected to slot [5798] located at 127.0.0.1:6100 //發現當沒有指定的key的時候會重定向到集群的其它機器去找 127.0.0.1:6100> set aaa 111 OK 127.0.0.1:6100> get aaa "111" //如上索性在6100實例的機器上面set aaa的值,然后在6200的機器上面去查 [mysql@localhost src]$ ./redis-cli -c -p 6200 127.0.0.1:6200> get aaa -> Redirected to slot [10439] located at 127.0.0.1:6100 //發現重定向去6100的端口的實例上找到了結果 "111" //在6200的機器上面直接重置aaa為1234 127.0.0.1:6200> set aaa 1234 -> Redirected to slot [10439] located at 127.0.0.1:6100 //還是重定向去6100的端口的實例上更新結果 OK
從上面的結果可以看出,集群中的節點是會進行通訊的,從而能找到不同的key在不同實例上,在機器固定的情況下,key唯一時后續對其的所有更新以及查詢都會映射到這一臺機器上面。
當然我們的集群的節點是不會一成不變的,我們隨時有可能擴容、縮容那該怎么來實現呢?下面來講講集群節點的變化吧。
四、集群變更
我們先在上面的基礎上試試添加端口為6300的實例,重復操作如上:
[mysql@localhost redis_cluster]$ mkdir 6300 [mysql@localhost redis_cluster]$ ll total 16 drwxrwxr-x. 2 mysql mysql 4096 Aug 21 05:40 6000 drwxrwxr-x. 2 mysql mysql 4096 Aug 21 05:40 6100 drwxrwxr-x. 2 mysql mysql 4096 Aug 21 05:40 6200 drwxrwxr-x. 2 mysql mysql 4096 Aug 21 06:27 6300 [mysql@localhost redis_cluster]$ cp ../redis/redis-3.2.3/src/redis-server ../redis/redis-3.2.3/redis.conf 6300/
不要忘了修改redis.conf,具體配置如上文提到的。
[mysql@localhost 6300]$ ./redis-server ./redis.conf [mysql@localhost 6300]$ netstat -an | grep 6300 tcp 0 0 0.0.0.0:16300 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:6300 0.0.0.0:* LISTEN tcp 0 0 :::16300 :::* LISTEN tcp 0 0 :::6300 :::* LISTEN
新的redis實例已經啟動好了,然后需要把它加到已有的集群啦:
./redis-trib.rb add-node 127.0.0.1:6300 127.0.0.1:6000
如上已經能查看到新的實例啦,為什么6300這個新的實例的connected后面沒有分配hash槽呢,別慌我們還沒有reshard, 執行如下命令:
./redis-trib.rb reshard 127.0.0.1:6300
我們想從6000節點中分配1000個hash槽位出來:
這樣有hash槽了,當crc16(key) / 16384 的結果在該節點的所在區間時,數據就放在該節點上。
redis 采用的crc16算法詳見:
https://blog.csdn.net/guodongxiaren/article/details/44706613
五、如何為每一個主節點增加從節點呢?
好吧,先創建6400端口實例看看,具體新建文件夾以及配置和重啟實例我就不再講了,上面以及有了。執行如下命令:
./redis-trib.rb add-node --slave 127.0.0.1:6400 127.0.0.1:6000
我們也可以試試在從節點6400上面做set操作:
127.0.0.1:6400> set da87 (error) ERR wrong number of arguments for 'set' command 127.0.0.1:6400> set da (error) ERR wrong number of arguments for 'set' command
很不幸,確實不能做set操作會報錯,從節點只能用于做讀工作。
六、我們如何來刪除一個節點呢? [mysql@localhost src]$ ./redis-trib.rb del-node 127.0.0.1:6000 'eb868ce2c102b897ee0a48cd8893288c36bacf5c' >>> Removing node eb868ce2c102b897ee0a48cd8893288c36bacf5c from cluster 127.0.0.1:6000 [ERR] Node 127.0.0.1:6000 is not empty! Reshard data away and try again. [mysql@localhost src]$
我們發現刪除6000端口的實例失敗了,應該是上面還有一些數據如果直接刪除就有數據丟失,我們應該把數據移到別的節點去:
./redis-trib.rb reshard 127.0.0.1:6000 //移除6000實例的數據 然后輸出了很多信息,很多數值和ID都可以從這段信息中找到。 How many slots do you want to move (from 1 to 16384)? 5461 會問你要移動多少個哈希槽,我們把 6000上的所有哈希槽都移走,5461 這個數字可以從終端上看到,或許你的實際情況不是這個數字。 What is the receiving node ID? d4467ece7cca245345b71cc1f639508f4f7831c4 //選定移動到6300端口的實例上面,實例ID Please enter all the source node IDs. Type 'all' to use all the nodes as source nodes for the hash slots. Type 'done' once you entered all the source nodes IDs. Source node #1:eb868ce2c102b897ee0a48cd8893288c36bacf5c //選定移除掉6000端口的實例上面,實例ID Source node #2:done 之后,redis 列出了重新分片計劃,最后問你 Do you want to proceed with the proposed reshard plan (yes/no)? yes
中間有一些重新分配的刷屏信息省略。
[mysql@localhost src]$ ./redis-cli -p 6300 127.0.0.1:6300> keys * 1) "aaa" 127.0.0.1:6300>
數據移到6300實例上面啦,我們再來試試刪除6000端口實例吧:
[mysql@localhost src]$ ./redis-trib.rb del-node 127.0.0.1:6000 'eb868ce2c102b897ee0a48cd8893288c36bacf5c' >>> Removing node eb868ce2c102b897ee0a48cd8893288c36bacf5c from cluster 127.0.0.1:6000 >>> Sending CLUSTER FORGET messages to the cluster... >>> SHUTDOWN the node. [mysql@localhost src]$ ./redis-cli -c -p 6000 Could not connect to Redis at 127.0.0.1:6000: Connection refused Could not connect to Redis at 127.0.0.1:6000: Connection refused
最終我們還是刪除成功啦!維護一個redis集群就是這么簡單。
號外號外:
現在我們公眾號推出參與獎和互動獎,凡是通過微信與我們參與討論互動最多的朋友,將獲得我們送出的神秘禮物,還有機會獲得Ansible中文官網馬上將出版的新書哦! 我們將不定期的推出獎勵計劃 ! 獎勵多多,小伙伴們,一起來吧!
以上是今天為大家帶來的內容,如果有任何問題,大家也可以添加以下QQ群參與問題的討論。
Ansible中文權威群:372011984(已滿)
AWK&SED企業實戰: 260039357
docker企業架構實踐:491533668
Jumpserver交流群 :399218702
Ansible中文權威-2號群:486022616
關于我們:
轉載請注明來自夕逆IT,本文標題:《AUG在《少女前線》中的適應性及屬性詳解?》

還沒有評論,來說兩句吧...