如何快速入門VUE3.0:進入學習
關於nodejs
中使用redis
集群功能,沒有找到一篇比較完整且通俗易懂的文章,因此自己在開發調試的過程中也走了不少彎路。
本文會詳細介紹了在本地如何建立redis叢集、在客戶端如何使用叢集、在建置過程中遇到的問題和錯誤彙總並說明,以避免下次使用的時候再走彎路,提高開發、工作效率。
使用群集的背景是:在Redis單例模式下隨著用戶量、訪問量的提高,qps值急劇上漲??,大量的io
操作導致某一時刻佔滿cpu(100%)
,隨時有宕機的危險,同時透過批次處理redis等方式也是治標不治本,無法突破伺服器效能的瓶頸。因此使用叢集方案或增加redis實例就勢在必行。
集群一般是指伺服器集群,區別於分散式系統,是將很多伺服器集中起來一起進行同一種服務,在客戶端看來就像是只有一個伺服器。叢集可以利用多台電腦進行平行運算從而獲得很高的運算速度,也可以用多台電腦做備份,這使得任何一個機器壞了整個系統還是能正常運作。 (在redis3.0之前一般使用的都是哨兵模式,但哨兵的配置略微複雜,並且性能和高可用性等各方面表現一般)
由於投票容錯機制要求超過半數節點認為某個節點掛了該節點才是掛了,所以2個節點無法構成集群,因此Redis集群至少需要3個節點。
要確保叢集的高可用、需要每個節點都有從節點(也就是備份節點),所以Redis
叢集至少需要6台伺服器。 (三主三從、三存三取、高可用、可備份)
當然,我們在本地調試時不可能用這麼多伺服器,因此我們可以在本地模擬運行6個redis
實例,事實上生產環境的Redis集群搭建和這裡基本上一樣。
可以在官網選擇安裝,也可以用命名行安裝
#安裝brew install redis #啟動redis-server #進入redis客戶端redis-cli
首先要找到redis設定檔的位置
brew list redis
# 查看redis安裝的位置cd /opt/homebrew/Cellar/redis/6.2.4
# 依照位置進入版本號所在的資料夾open .
# 開啟資料夾Xcode.app
開啟homebrew.mxcl.redis.plist
, 即可找到redis.conf
所在的位置,如下所示:建立六個服務設定檔
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到上面建立的redis/cluster/7000
目錄下,然後再修改,步驟如下
cd /opt/homebrew/etc/ # 進入設定檔目錄cp redis.conf redis/cluster/7000/7000.conf code redis/cluster/7000/7000.conf # 用編輯器開啟或用vim開啟設定檔來進行修改
7000.conf
後,修改以下屬性# Redis埠號(7000-7005每個設定檔都要修改) port 7000 # 開啟叢集模式運行cluster-enabled yes # 叢集內部設定檔設定檔路徑,預設nodes-6379.conf(7000-7005每個設定檔都要修改) cluster-config-file nodes-7000.conf # 節點間通訊的超時時間cluster-node-timeout 5000 # 資料持久化appendonly yes
cd /opt/homebrew/etc/redis/cluster # 進入設定檔目錄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
每個設定檔的port和cluster-config-file屬性注意:每個設定檔必需設定不一樣的port和cluster-config-file
值(否則叢集不會生效),上面是以連接埠區分。
透過find /opt/homebrew -name nodes-7000.conf
指令可查找到該設定檔的目錄
由於我們配置了6個服務,因此不可能一個一個的啟動或停止,需要藉助shell腳本來實現
進入/opt/homebrew/etc/redis/cluster
目錄,創建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 &
執行./start.sh
或./stop.sh
來啟動停止服務
執行ps -ef |grep redis
來查看已啟動的redis服務
注意:第一次執行./start.sh需要透過sudo chmod +x start.sh
授權執行權限
redis-cli -p 7000 # 單一客戶端啟動redis-server 7000/7000.conf # 啟動單一服務端redis-cli -p 7000 shutdown # 關閉服務端sudo chmod +x start.sh # 開啟腳本執行權限# 設定redis主從關係式(三主三從) 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:70. cluster nodes #查看叢集節點狀況(進入某個客戶端執行) cluster info #查看叢集資訊(進入某個客戶端執行) 查看所有key值:keys * 刪除指定索引的值:del key 清空整個Redis 伺服器的資料:flushall 清空目前庫中的所有key:flushdb
Redis.Cluster提供了在多個Redis節點上自動分片的功能,使用前面搭建好的六個redis伺服器,然後在本地啟動node redis.js
,就可以測試叢集的效果了。 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' });
import Queue from 'bull' // 建立redis佇列實例const instance = new Queue('custom', { prefix : '{myprefix}', createClient(type) { // cluster 叢集實例同上return cluster } }) // 將資料加入redis隊列(生產者) instance.add( 'request', { ....params }, { removeOnComplete: false } ).catch(e => { console.error(e) }) // 消費者回呼instance.process('request', 5, async (job, done) => { console.log('取得目前消費的資料:', job.data) // 執行非同步操作await new Promise((resolve)=>resolve()) done() })
使用bull
框架連接ioredis
叢集時存在問題: 每次有資料push
到redis
佇列時對應的回呼函數可能會觸發多次,目前無法確定是使用的問題還是框架本身的問題(如果有了解的歡迎大家留言告知)。
替代叢集的方案:在不需要資料同步和資料遷移的情況下,可以在客戶端使用多個redis
實例,結合Math.random()
使資料平分到其中的一個redis
,從而解決了單一實例硬體( cpu
等)瓶頸的問題。
1、Mac系統下連接redis報錯?
控制台錯誤提示:Could not connect to Redis at 127.0.0.1:6379: Connection refused
原因:服務端沒有開啟或啟動失敗
解決方案:需要先啟動redis服務端redis-server
參考連結
https://blog.csdn. net/qq_23347459/article/details/104257529
2、客戶端啟動、讀寫報錯?
錯誤提示:ClusterAllFailedError: Failed to refresh slots cache.
原因:每個服務下的設定檔中的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、執行創建主從redis語句失敗?
執行語句: 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
[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
原因:執行建立語句時,沒有清空資料和重設叢集處理:清空資料和重設叢集
處理:清空資料和重置叢集, 清除rdb和aof檔案
參考清除redis資料
https://stackoverflow.com/questions/37206993/redis-server-cluster-not-working
# 以7000連接埠的服務為例,7001-7005重複以下操作$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# 重新執行建立
成功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 170.1:7002 127.0.0.1:7003 17.0.0.
redis叢集在客戶端的使用是非常簡單的,相較之下服務端的配置會比較繁瑣。
客戶端的具體使用只做了簡單的說明,使用過程中要注意redis資料的同步與遷移等問題。
使用叢集雖然能提升服務能力、支援主從複製、哨兵模式、讀寫分離、平分伺服器的壓力等特性。但不具備自動容錯和復原功能,如果出現宕機會使部分讀寫請求失敗,降低了系統的可用性。使用時根據業務狀況分析、選擇不同的方案。
本文轉載自:https://juejin.cn/post/7079928963107127327
作者:tager