一、為什么要弄redis集群
集群技術(shù)是構(gòu)建高性能網(wǎng)站架構(gòu)的重要手段,試想在網(wǎng)站承受高并發(fā)訪問壓力的同時(shí),還需要從海量數(shù)據(jù)中查詢出滿足條件的數(shù)據(jù),并快速響應(yīng),我們必然想到的是將數(shù)據(jù)進(jìn)行切片,把數(shù)據(jù)根據(jù)某種規(guī)則放入多個不同的服務(wù)器節(jié)點(diǎn),來降低單節(jié)點(diǎn)服務(wù)器的壓力。上篇redis_主從我們講到了 Redis 的主從復(fù)制技術(shù),當(dāng)實(shí)現(xiàn)了多節(jié)點(diǎn)的 master-slave 后,我們也可以把它叫做集群,但我們今天要講的集群主要是利用切片技術(shù)來組建的集群。我們最后希望達(dá)到的是類似下圖:
二、實(shí)現(xiàn)策略
因?yàn)閺?.0開始以后官方已經(jīng)支持了 redis cluster,https://redis.io/topics/cluster-tutorial
集群要實(shí)現(xiàn)的目的是要將不同的 key 分散放置到不同的 redis 節(jié)點(diǎn),這里我們需要一個規(guī)則或者算法,通常的做法是獲取 key 的哈希值,然后根據(jù)節(jié)點(diǎn)數(shù)來求模,但這種做法有其明顯的弊端,當(dāng)我們需要增加或減少一個節(jié)點(diǎn)時(shí),會造成大量的 key 無法命中,這種比例是相當(dāng)高的,所以就有人提出了一致性哈希的概念。
由于官方版本是基于哈希槽(hash slot)的概念來實(shí)現(xiàn)的,我們還是從其官方介紹中翻譯解釋一下:
Redis 集群中內(nèi)置了 16384 個哈希槽,當(dāng)需要在 Redis 集群中放置一個 key-value 時(shí),redis 先對 key 使用 crc16 算法算出一個結(jié)果,然后把結(jié)果對 16384 求余數(shù),這樣每個 key 都會對應(yīng)一個編號在 0-16383 之間的哈希槽,redis 會根據(jù)節(jié)點(diǎn)數(shù)量大致均等的將哈希槽映射到不同的節(jié)點(diǎn)。
使用哈希槽的好處就在于可以方便的添加或移除節(jié)點(diǎn):
當(dāng)需要增加節(jié)點(diǎn)時(shí),只需要把其他節(jié)點(diǎn)的某些哈希槽挪到新節(jié)點(diǎn)就可以了;
當(dāng)需要移除節(jié)點(diǎn)時(shí),只需要把移除節(jié)點(diǎn)上的哈希槽挪到其他節(jié)點(diǎn)就行了;
三、集群實(shí)現(xiàn)
對于我們來說,在新增或移除節(jié)點(diǎn)的能做到無縫(即不需要重啟集群),這點(diǎn)它做到了。還是來看看具體的實(shí)現(xiàn)吧:
新建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文件因?yàn)槲覀儐拥亩丝谑遣灰粯拥?vi redis.conf刪除里面的所有添加如下的:
daemonize yes //指定以守護(hù)進(jìn)程啟動 port 6000 //啟動端口 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes
依次啟動每一個實(shí)例文件夾下面的./redis-server ./redis.conf,這樣的話3個實(shí)例就啟動了,但是如何將3個實(shí)例維護(hù)成一個集群呢,在src目錄下面執(zhí)行:
./redis-trib.rb create --replicas 0 127.0.0.1:6000 127.0.0.1:6100 127.0.0.1:6200
執(zhí)行以后是不是會發(fā)現(xiàn)執(zhí)行失敗提示沒有redis-trib.rb文件,好吧我們還忘了裝一個,因?yàn)槲覀儓?zhí)行的是ruby命令,所以還需要安裝ruby:
https://rubygems.org/gems/redis下載,然后離線安裝。sudo gem install redis-3.3.1.gem --local
安裝完成以后再src目錄下面就有了redis-trib.rb文件。
執(zhí)行上面的集群命令控制臺輸出如下:
來試試集群的效果吧:
在6000端口實(shí)例上測試 [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 //發(fā)現(xiàn)當(dāng)沒有指定的key的時(shí)候會重定向到集群的其它機(jī)器去找 127.0.0.1:6100> set aaa 111 OK 127.0.0.1:6100> get aaa "111" //如上索性在6100實(shí)例的機(jī)器上面set aaa的值,然后在6200的機(jī)器上面去查 [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 //發(fā)現(xiàn)重定向去6100的端口的實(shí)例上找到了結(jié)果 "111" //在6200的機(jī)器上面直接重置aaa為1234 127.0.0.1:6200> set aaa 1234 -> Redirected to slot [10439] located at 127.0.0.1:6100 //還是重定向去6100的端口的實(shí)例上更新結(jié)果 OK
從上面的結(jié)果可以看出,集群中的節(jié)點(diǎn)是會進(jìn)行通訊的,從而能找到不同的key在不同實(shí)例上,在機(jī)器固定的情況下,key唯一時(shí)后續(xù)對其的所有更新以及查詢都會映射到這一臺機(jī)器上面。
當(dāng)然我們的集群的節(jié)點(diǎn)是不會一成不變的,我們隨時(shí)有可能擴(kuò)容、縮容那該怎么來實(shí)現(xiàn)呢?下面來講講集群節(jié)點(diǎn)的變化吧。
四、集群變更
我們先在上面的基礎(chǔ)上試試添加端口為6300的實(shí)例,重復(fù)操作如上:
[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實(shí)例已經(jīng)啟動好了,然后需要把它加到已有的集群啦:
./redis-trib.rb add-node 127.0.0.1:6300 127.0.0.1:6000
如上已經(jīng)能查看到新的實(shí)例啦,為什么6300這個新的實(shí)例的connected后面沒有分配hash槽呢,別慌我們還沒有reshard, 執(zhí)行如下命令:
./redis-trib.rb reshard 127.0.0.1:6300
我們想從6000節(jié)點(diǎn)中分配1000個hash槽位出來:
這樣有hash槽了,當(dāng)crc16(key) / 16384 的結(jié)果在該節(jié)點(diǎn)的所在區(qū)間時(shí),數(shù)據(jù)就放在該節(jié)點(diǎn)上。
redis 采用的crc16算法詳見:
https://blog.csdn.net/guodongxiaren/article/details/44706613
五、如何為每一個主節(jié)點(diǎn)增加從節(jié)點(diǎn)呢?
好吧,先創(chuàng)建6400端口實(shí)例看看,具體新建文件夾以及配置和重啟實(shí)例我就不再講了,上面以及有了。執(zhí)行如下命令:
./redis-trib.rb add-node --slave 127.0.0.1:6400 127.0.0.1:6000
我們也可以試試在從節(jié)點(diǎn)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
很不幸,確實(shí)不能做set操作會報(bào)錯,從節(jié)點(diǎn)只能用于做讀工作。
六、我們?nèi)绾蝸韯h除一個節(jié)點(diǎn)呢? [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]$
我們發(fā)現(xiàn)刪除6000端口的實(shí)例失敗了,應(yīng)該是上面還有一些數(shù)據(jù)如果直接刪除就有數(shù)據(jù)丟失,我們應(yīng)該把數(shù)據(jù)移到別的節(jié)點(diǎn)去:
./redis-trib.rb reshard 127.0.0.1:6000 //移除6000實(shí)例的數(shù)據(jù) 然后輸出了很多信息,很多數(shù)值和ID都可以從這段信息中找到。 How many slots do you want to move (from 1 to 16384)? 5461 會問你要移動多少個哈希槽,我們把 6000上的所有哈希槽都移走,5461 這個數(shù)字可以從終端上看到,或許你的實(shí)際情況不是這個數(shù)字。 What is the receiving node ID? d4467ece7cca245345b71cc1f639508f4f7831c4 //選定移動到6300端口的實(shí)例上面,實(shí)例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端口的實(shí)例上面,實(shí)例ID Source node #2:done 之后,redis 列出了重新分片計(jì)劃,最后問你 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>
數(shù)據(jù)移到6300實(shí)例上面啦,我們再來試試刪除6000端口實(shí)例吧:
[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
最終我們還是刪除成功啦!維護(hù)一個redis集群就是這么簡單。
號外號外:
現(xiàn)在我們公眾號推出參與獎和互動獎,凡是通過微信與我們參與討論互動最多的朋友,將獲得我們送出的神秘禮物,還有機(jī)會獲得Ansible中文官網(wǎng)馬上將出版的新書哦! 我們將不定期的推出獎勵計(jì)劃 ! 獎勵多多,小伙伴們,一起來吧!
以上是今天為大家?guī)淼膬?nèi)容,如果有任何問題,大家也可以添加以下QQ群參與問題的討論。
Ansible中文權(quán)威群:372011984(已滿)
AWK&SED企業(yè)實(shí)戰(zhàn): 260039357
docker企業(yè)架構(gòu)實(shí)踐:491533668
Jumpserver交流群 :399218702
Ansible中文權(quán)威-2號群:486022616
關(guān)于我們:
轉(zhuǎn)載請注明來自夕逆IT,本文標(biāo)題:《AUG在《少女前線》中的適應(yīng)性及屬性詳解?》

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