node中怎么使用redis集群功能?下面本篇文章給大家詳解一下基于node的redis集群配置,希望對(duì)大家有所幫助!
關(guān)于nodejs
中使用redis
集群功能,沒(méi)有找到一篇比較完整且通俗易懂的文章,因此自己在開(kāi)發(fā)調(diào)試的過(guò)程中也走了不少?gòu)澛贰?/p>
本文會(huì)詳細(xì)介紹了在本地如何搭建redis集群、在客戶端如何使用集群、在搭建過(guò)程中遇到的問(wèn)題和錯(cuò)誤匯總并說(shuō)明,以避免下次使用的時(shí)候再走彎路,提高開(kāi)發(fā)、工作效率。
使用集群的背景是:在Redis單例模式下隨著用戶量、訪問(wèn)量的提高,qps值急劇上漲??,大量的io
操作導(dǎo)致某一時(shí)刻占滿cpu(100%)
,隨時(shí)有宕機(jī)的危險(xiǎn),同時(shí)通過(guò)批量處理redis等方式也是治標(biāo)不治本,無(wú)法突破服務(wù)器性能的瓶頸。因此使用集群方案或增加redis實(shí)例就勢(shì)在必行。
名詞解釋–集群
集群一般是指服務(wù)器集群,區(qū)別于分布式系統(tǒng),是將很多服務(wù)器集中起來(lái)一起進(jìn)行同一種服務(wù),在客戶端看來(lái)就像是只有一個(gè)服務(wù)器。集群可以利用多個(gè)計(jì)算機(jī)進(jìn)行并行計(jì)算從而獲得很高的計(jì)算速度,也可以用多個(gè)計(jì)算機(jī)做備份,從而使得任何一個(gè)機(jī)器壞了整個(gè)系統(tǒng)還是能正常運(yùn)行。(在redis3.0之前一般使用的都是 哨兵模式,但 哨兵的配置略微復(fù)雜,并且性能和高可用性等各方面表現(xiàn)一般)
redis集群要求
由于投票容錯(cuò)機(jī)制要求超過(guò)半數(shù)節(jié)點(diǎn)認(rèn)為某個(gè)節(jié)點(diǎn)掛了該節(jié)點(diǎn)才是掛了,所以2個(gè)節(jié)點(diǎn)無(wú)法構(gòu)成集群,因此Redis集群至少需要3個(gè)節(jié)點(diǎn)。
要保證集群的高可用、需要每個(gè)節(jié)點(diǎn)都有從節(jié)點(diǎn)(也就是備份節(jié)點(diǎn)),所以Redis
集群至少需要6臺(tái)服務(wù)器。 (三主三從、三存三取、高可用、可備份)
當(dāng)然,我們?cè)诒镜卣{(diào)試時(shí)不可能用這么多服務(wù)器,因此我們可以在本地模擬運(yùn)行6個(gè)redis
實(shí)例,事實(shí)上生產(chǎn)環(huán)境的Redis集群搭建和這里基本上一樣。
mac 環(huán)境下搭建本地redis集群
1. 下載安裝redis
可以在官網(wǎng)選擇安裝,也可以用命名行安裝
#安裝 brew install redis #啟動(dòng) redis-server #進(jìn)入redis客戶端 redis-cli
2. 通過(guò)redis配置集群環(huán)境
首先要找到redis配置文件的位置
brew list redis
# 查看redis安裝的位置cd /opt/homebrew/Cellar/redis/6.2.4
# 根據(jù)位置進(jìn)入版本號(hào)所在的文件夾open .
# 打開(kāi)文件夾- 用
Xcode.app
打開(kāi)homebrew.mxcl.redis.plist
, 即可找到redis.conf
所在的位置,如下所示:
創(chuàng)建六個(gè)服務(wù)配置文件
cd /opt/homebrew/etc/
(上一步找到的配置文件目錄)
# 需要在 /opt/homebrew/etc/ 路徑下 mkdir -p redis/cluster/7000 mkdir -p redis/cluster/7001 mkdir -p redis/cluster/7002 mkdir -p redis/cluster/7003 mkdir -p redis/cluster/7004 mkdir -p redis/cluster/7005
修改配置文件
/opt/homebrew/etc/redis.conf
路徑下的配置文件不用去修改, 只要將其copy到上面創(chuàng)建的 redis/cluster/7000
目錄下,然后再修改,步驟如下
- 先復(fù)制一份配置文件修改
cd /opt/homebrew/etc/ # 進(jìn)入配置文件目錄 cp redis.conf redis/cluster/7000/7000.conf code redis/cluster/7000/7000.conf # 用編輯器打開(kāi)或者用vim打開(kāi)配置文件來(lái)進(jìn)行修改
- 進(jìn)入到
7000.conf
后,修改以下屬性
# Redis端口號(hào)(7000-7005每個(gè)配置文件都要修改) port 7000 # 開(kāi)啟集群模式運(yùn)行 cluster-enabled yes # 集群內(nèi)部配置文件配置文件路徑,默認(rèn)nodes-6379.conf(7000-7005每個(gè)配置文件都要修改) cluster-config-file nodes-7000.conf # 節(jié)點(diǎn)間通信的超時(shí)時(shí)間 cluster-node-timeout 5000 # 數(shù)據(jù)持久化 appendonly yes
- 將7000.conf復(fù)制到每個(gè)redis服務(wù)的目錄下
cd /opt/homebrew/etc/redis/cluster # 進(jìn)入配置文件目錄 cp 7000/7000.conf 7001/7001.conf cp 7000/7000.conf 7002/7002.conf cp 7000/7000.conf 7003/7003.conf cp 7000/7000.conf 7004/7004.conf cp 7000/7000.conf 7005/7005.conf
- 再修改
7001.conf-7005.conf
每個(gè)配置文件的port和cluster-config-file屬性
注意:每個(gè)配置文件必需配置不一樣的port和cluster-config-file
值(否則集群不會(huì)生效),上面是以端口區(qū)分。
通過(guò)find /opt/homebrew -name nodes-7000.conf
命令可查找到該配置文件的目錄
3. 啟動(dòng)和停止集群服務(wù)
由于我們配置了6個(gè)服務(wù),因此不可能一個(gè)一個(gè)的啟動(dòng)或停止,需要借助shell腳本來(lái)實(shí)現(xiàn)
進(jìn)入/opt/homebrew/etc/redis/cluster
目錄,創(chuàng)建start.sh和stop.sh文件
# start.sh 文件 #!/bin/sh redis-server /opt/homebrew/etc/redis/cluster/7000/7000.conf & redis-server /opt/homebrew/etc/redis/cluster/7001/7001.conf & redis-server /opt/homebrew/etc/redis/cluster/7002/7002.conf & redis-server /opt/homebrew/etc/redis/cluster/7003/7003.conf & redis-server /opt/homebrew/etc/redis/cluster/7004/7004.conf & redis-server /opt/homebrew/etc/redis/cluster/7005/7005.conf & # stop.sh 文件 #!/bin/sh redis-cli -p 7000 shutdown & redis-cli -p 7001 shutdown & redis-cli -p 7002 shutdown & redis-cli -p 7003 shutdown & redis-cli -p 7004 shutdown & redis-cli -p 7005 shutdown &
執(zhí)行./start.sh
或者./stop.sh
來(lái)啟停服務(wù)
執(zhí)行ps -ef |grep redis
來(lái)查看已啟動(dòng)的redis服務(wù)
注意: 第一次執(zhí)行./start.sh需要通過(guò)sudo chmod +x start.sh
授權(quán)執(zhí)行權(quán)限
4. 相關(guān)命令
redis-cli -p 7000 # 單個(gè)客戶端啟動(dòng) redis-server 7000/7000.conf # 啟動(dòng)單個(gè)服務(wù)端 redis-cli -p 7000 shutdown # 關(guān)閉服務(wù)端 sudo chmod +x start.sh # 開(kāi)啟腳本執(zhí)行權(quán)限 # 設(shè)置redis主從關(guān)系(三主三從) redis-cli --cluster create --cluster-replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 cluster nodes #查看集群節(jié)點(diǎn)情況(進(jìn)入某個(gè)客戶端執(zhí)行) cluster info #查看集群信息(進(jìn)入某個(gè)客戶端執(zhí)行) 查看所有key值:keys * 刪除指定索引的值:del key 清空整個(gè) Redis 服務(wù)器的數(shù)據(jù):flushall 清空當(dāng)前庫(kù)中的所有 key:flushdb
客戶端使用 ioredis 框架接入集群
Redis.Cluster提供了在多個(gè)Redis節(jié)點(diǎn)上自動(dòng)分片的功能,使用前面搭建好的六個(gè)redis服務(wù)器,然后在本地啟動(dòng)node redis.js
,就可以測(cè)試集群的效果了。ioredis
// redis.js const Redis = require("ioredis"); const cluster = new Redis.Cluster([ { port: 7000, host: "127.0.0.1", }, { port: 7001, host: "127.0.0.1", }, ]); cluster.set("foo", "bar"); cluster.get("foo", (err, res) => { // res === 'bar' });
使用bull框架(redis 隊(duì)列)
import Queue from 'bull' // 創(chuàng)建redis隊(duì)列實(shí)例 const instance = new Queue('custom', { prefix : '{myprefix}', createClient(type) { // cluster 集群實(shí)例同上 return cluster } }) // 添加數(shù)據(jù)到redis隊(duì)列(生產(chǎn)者) instance.add( 'request', { ...params }, { removeOnComplete: false } ).catch(e => { console.error(e) }) // 消費(fèi)者回調(diào) instance.process('request', 5, async (job, done) => { console.log('獲取當(dāng)前消費(fèi)的數(shù)據(jù):', job.data) // 執(zhí)行異步操作 await new Promise((resolve)=>resolve()) done() })
使用bull
框架連接ioredis
集群時(shí)存在問(wèn)題: 每次有數(shù)據(jù)push
到redis
隊(duì)列時(shí)對(duì)應(yīng)的回調(diào)函數(shù)可能會(huì)觸發(fā)多次,目前無(wú)法確定是使用的問(wèn)題還是框架本身的問(wèn)題(如果有了解的歡迎大家留言告知)。
替代集群的方案:在不需要數(shù)據(jù)同步和數(shù)據(jù)遷移的情況下,可以在客戶端使用多個(gè)redis
實(shí)例,結(jié)合Math.random()
使數(shù)據(jù)平分到其中的一個(gè)redis
,從而解決了單個(gè)實(shí)例硬件(cpu
等)瓶頸的問(wèn)題。
問(wèn)題處理
1、Mac系統(tǒng)下連接redis報(bào)錯(cuò)?
控制臺(tái)錯(cuò)誤提示:Could not connect to Redis at 127.0.0.1:6379: Connection refused
原因:服務(wù)端沒(méi)有開(kāi)啟或啟動(dòng)失敗
解決辦法:需要先啟動(dòng)redis服務(wù)端redis-server
參考鏈接
https://blog.csdn.net/qq_23347459/article/details/104257529
2、客戶端啟動(dòng)、讀寫(xiě)報(bào)錯(cuò)?
錯(cuò)誤提示:ClusterAllFailedError: Failed to refresh slots cache.
原因:每個(gè)服務(wù)下的配置文件中的cluster-config-file屬性一致。
處理:修改成唯一的屬性值
參考鏈接1
https://stackoverflow.com/questions/57350961/ioredis-clusterallfailederror-failed-to-refresh-slots-cache
參考2
https://github.com/luin/ioredis/issues/711
3、執(zhí)行創(chuàng)建主從redis語(yǔ)句失???
執(zhí)行語(yǔ)句:redis-cli --cluster create --cluster-replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
提示錯(cuò)誤:[ERR] Node 127.0.0.1:7000 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0
原因:執(zhí)行創(chuàng)建語(yǔ)句時(shí),沒(méi)有清空數(shù)據(jù)和重置集群
處理:清空數(shù)據(jù)和重置集群, 清除rdb和aof文件
參考清除redis數(shù)據(jù)
https://stackoverflow.com/questions/37206993/redis-server-cluster-not-working
# 以7000端口的服務(wù)為例,7001-7005重復(fù)以下操作 $redis-cli -p 7000 127.0.0.1:7000> flushall 127.0.0.1:7000> cluster reset 127.0.0.1:7000> exit # 使用find找到rdb和aof文件(也在rdb目錄下) find /opt/homebrew -name dump.rdb # 重新執(zhí)行創(chuàng)建語(yǔ)句成功 redis-cli --cluster create --cluster-replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
結(jié)語(yǔ)
redis集群在客戶端的使用是非常簡(jiǎn)單的,相比之下服務(wù)端的配置會(huì)比較繁瑣。
客戶端的具體使用只做了一下簡(jiǎn)單的說(shuō)明,使用過(guò)程中要注意redis數(shù)據(jù)的同步和遷移等問(wèn)題。
使用集群雖然能提升服務(wù)能力、支持主從復(fù)制、哨兵模式、讀寫(xiě)分離、平分服務(wù)器的壓力等特點(diǎn)。但不具備自動(dòng)容錯(cuò)和恢復(fù)功能,如果出現(xiàn)宕機(jī)會(huì)使部分讀寫(xiě)請(qǐng)求失敗,降低了系統(tǒng)的可用性。在使用時(shí)根據(jù)業(yè)務(wù)情況分析、選擇不同的方案。
本文轉(zhuǎn)載自:https://juejin.cn/post/7079928963107127327
作者:tager