三分鐘快速搭建分散式高可用的Redis集群

来源:https://www.cnblogs.com/heihaozi/archive/2020/05/12/12874093.html
-Advertisement-
Play Games

Redis Cluster是Redis在3.0版本正式推出的專用集群方案,有效地解決了Redis分散式方面的需求,讓我們一起快速搭建出分散式高可用的Redis集群吧! ...


這裡的Redis集群指的是Redis Cluster,它是Redis在3.0版本正式推出的專用集群方案,有效地解決了Redis分散式方面的需求。當單機記憶體、併發、流量等遇到瓶頸的時候,可以採用這種Redis Cluster方案進行解決。

分區規則

Redis Cluster採用虛擬槽(slot)進行數據分區,即使用分散度良好的哈希函數把所有鍵映射到一個固定範圍的整數集合里,這裡的整數就是槽(slot)。Redis Cluster槽的範圍是0~16383,計算公式:slot=CRC16(key) & 16383。

白嫖小貼士:CRC16是一種高質量的哈希演算法,可以使每個槽所映射的鍵通常比較均勻。

當集群中有3個節點時,每個節點平均大概負責5461個槽以及槽所映射的鍵值數據。這樣一來,可以解耦數據與節點之間的關係,簡化節點擴容和縮容的難度。節點自身維護槽的映射關係,不需要客戶端或代理服務維護分區信息。

不過,Redis Cluster相對於單機還是存在一些限制的,比如:

  1. 批量操作鍵支持有限,僅支持具有相同槽的鍵進行批量操作。
  2. 事務操作鍵支持有限,僅支持在同一個節點上多個鍵的事務操作。
  3. 不支持多個數據空間。單機Redis可以支持16個資料庫,而Cluster模式下只能使用一個資料庫空間。

扯了這麼多Redis Cluster的分區規則,下麵我們開始步入正題。

歡迎關註微信公眾號:萬貓學社,每周一分享Java技術乾貨。

手動搭建

把Redis Cluster搭建起來總共幾步?答:三步!第一步把冰箱門打開。第二步把大象關進去。第三步把冰箱門帶上。不好意思,段子暴露年齡了。集群搭建需要以下三個步驟:

  1. 準備節點。
  2. 節點握手。
  3. 分配槽。

Redis Cluster由多個節點組成,節點數量至少有6個才能組成一個完整高可用的集群,其中有3個主節點和3個從節點,我們就以此為例搭建一個Redis Cluster。

準備節點

首先,為6個節點(同一臺機器上的6380、6381、6382、6383、6384、6385埠)分別創建配置文件,以6380埠的節點為例:

# 節點埠
port 6380
#日誌文件
logfile "log/redis-6380.log"
# 開啟集群模式
cluster-enabled yes
# 集群配置文件
cluster-config-file "data/nodes-6380.conf"

保持文件名為redis-6380.conf,其他節點的配置文件替換成各自的埠。準備好配置文件後啟動所有節點,命令如下:

src/redis-server conf/redis-6380.conf &
src/redis-server conf/redis-6381.conf &
src/redis-server conf/redis-6382.conf &
src/redis-server conf/redis-6383.conf &
src/redis-server conf/redis-6384.conf &
src/redis-server conf/redis-6385.conf &

檢測日誌是否正確,以下是6380埠的節點的日誌:

 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
 # Redis version=4.0.14, bits=64, commit=00000000, modified=0, pid=3031, just started
 # Configuration loaded
 * No cluster configuration found, I'm df1ac987f47dea35f1d0a83c3b405f0ef86892ab
 * Running mode=cluster, port=6380.

6380埠的節點啟動成功,第一次啟動時如果沒有集群配置文件,Redis會自動創建一個。6380埠的節點創建的集群配置文件如下:

df1ac987f47dea35f1d0a83c3b405f0ef86892ab :0@0 myself,master - 0 0 0 connected
vars currentEpoch 0 lastVoteEpoch 0

集群文件中記錄的集群的狀態,這裡最重要的是節點ID,它是一個40位的16進位字元串,用於唯一標識集群中的這個節點。同樣,也可以通過cluster nodes命令查看集群節點狀態。比如在6380埠的節點上執行命令:

127.0.0.1:6380> cluster nodes
df1ac987f47dea35f1d0a83c3b405f0ef86892ab :6380@16380 myself,master - 0 0 0 connected

目前,我們已經成功啟動了6個節點,但是它們只能識別自己的節點信息,互相之間並不認識。下麵我們通過節點握手讓這6個節點互相之間建立聯繫從而組成一個集群。

歡迎關註微信公眾號:萬貓學社,每周一分享Java技術乾貨。

節點握手

節點握手是一些運行在集群模式下的節點通過Gossip協議互相通信,達到感知彼此的過程。

白嫖小貼士:Gossip協議是基於流行病傳播方式的節點或者進程之間信息交換的協議,在分散式系統中被廣泛使用。

節點握手通過客戶端執行cluster meet命令實現,它是一個非同步命令,執行之後立刻返回,在Redis內部非同步發起與目標節點的握手通信,該命令的語法如下:

cluster meet 目標節點IP 目標節點埠

把6個節點加到一個集群中:

127.0.0.1:6380> cluster meet 127.0.0.1 6381
OK
127.0.0.1:6380> cluster meet 127.0.0.1 6382
OK
127.0.0.1:6380> cluster meet 127.0.0.1 6383
OK
127.0.0.1:6380> cluster meet 127.0.0.1 6384
OK
127.0.0.1:6380> cluster meet 127.0.0.1 6385
OK

只需要在集群中任意節點上執行cluster meet命令加入新的節點,握手狀態會通過消息在集群中傳播,其他節點也會自動發現新節點並與之發起握手流程。

我們再執行一下cluster nodes命令,檢查一下6個節點是否已經組成集群:

127.0.0.1:6380> cluster nodes
1e1f45677d7b9b0130d03193f0bcec34578ac47d 127.0.0.1:6385@16385 master - 0 1586617919021 5 connected
df1ac987f47dea35f1d0a83c3b405f0ef86892ab 127.0.0.1:6380@16380 myself,master - 0 1586617916000 2 connected
5846b66ebe4fb4a5dcfd035652cc471f7e412752 127.0.0.1:6381@16381 master - 0 1586617917005 1 connected
a435cf98c3444b0b110a224401e397a107c453ef 127.0.0.1:6384@16384 master - 0 1586617914988 4 connected
71e0e9e9a6f0c7c85dbe0d396846a9072625c5e8 127.0.0.1:6383@16383 master - 0 1586617918013 3 connected
e25590603c7a254cce43aa8437861c5c425d753d 127.0.0.1:6382@16382 master - 0 1586617916000 0 connected

可以看到,6個節點都在集群中了。不過,此時因為還沒有為集群中的節點分配槽,集群還處於下線狀態,所有的數據讀寫都是被禁止的。比如:

127.0.0.1:6380> set onemore study
(error) CLUSTERDOWN Hash slot not served

接下來,我們為集群中的節點分配槽。

分配槽

我們把6380、6382、6384埠的節點作為主節點,負責處理槽和相關數據;6381、6383、6385埠的節點分別作為從節點,負責故障轉移。先把16384個槽平均分配給6380、6382、6384埠的節點,為節點分配槽是通過cluster addslots命令實現:

# ./redis-cli -h 127.0.0.1  -p 6380 cluster addslots {0..5461}
OK
# ./redis-cli -h 127.0.0.1  -p 6382 cluster addslots {5462..10922}
OK
# ./redis-cli -h 127.0.0.1  -p 6384 cluster addslots {10923..16383}
OK

我們再執行一下cluster nodes命令,檢查一下槽是否已經分配:

127.0.0.1:6380> cluster nodes
1e1f45677d7b9b0130d03193f0bcec34578ac47d 127.0.0.1:6385@16385 master - 0 1586619468000 5 connected
df1ac987f47dea35f1d0a83c3b405f0ef86892ab 127.0.0.1:6380@16380 myself,master - 0 1586619464000 2 connected 0-5461
5846b66ebe4fb4a5dcfd035652cc471f7e412752 127.0.0.1:6381@16381 master - 0 1586619467000 1 connected
a435cf98c3444b0b110a224401e397a107c453ef 127.0.0.1:6384@16384 master - 0 1586619467000 4 connected 10923-16383
71e0e9e9a6f0c7c85dbe0d396846a9072625c5e8 127.0.0.1:6383@16383 master - 0 1586619467348 3 connected
e25590603c7a254cce43aa8437861c5c425d753d 127.0.0.1:6382@16382 master - 0 1586619468355 0 connected 5462-10922

再使用cluster replicate命令把一個節點變成從節點.,這個命令必須在從節點上運行,它的語法是:

cluster replicate 主節點ID

把6381、6383、6385埠的節點變成對應6380、6382、6384埠的節點的從節點:

# ./redis-cli -h 127.0.0.1  -p 6381
127.0.0.1:6381> cluster replicate df1ac987f47dea35f1d0a83c3b405f0ef86892ab
OK
127.0.0.1:6381> exit
# ./redis-cli -h 127.0.0.1  -p 6383
127.0.0.1:6383> cluster replicate e25590603c7a254cce43aa8437861c5c425d753d
OK
127.0.0.1:6383> exit
# ./redis-cli -h 127.0.0.1  -p 6385
127.0.0.1:6385> cluster replicate a435cf98c3444b0b110a224401e397a107c453ef
OK
127.0.0.1:6385> exit

我們再執行一下cluster nodes命令,檢查一下集群狀態和主從關係:

127.0.0.1:6380> cluster nodes
df1ac987f47dea35f1d0a83c3b405f0ef86892ab 127.0.0.1:6380@16380 myself,master - 0 1586620148000 2 connected 0-5461
5846b66ebe4fb4a5dcfd035652cc471f7e412752 127.0.0.1:6381@16381 slave df1ac987f47dea35f1d0a83c3b405f0ef86892ab 0 1586620150000 2 connected
e25590603c7a254cce43aa8437861c5c425d753d 127.0.0.1:6382@16382 master - 0 1586620151000 0 connected 5462-10922
71e0e9e9a6f0c7c85dbe0d396846a9072625c5e8 127.0.0.1:6383@16383 slave e25590603c7a254cce43aa8437861c5c425d753d 0 1586620152220 3 connected
a435cf98c3444b0b110a224401e397a107c453ef 127.0.0.1:6384@16384 master - 0 1586620150000 4 connected 10923-16383
1e1f45677d7b9b0130d03193f0bcec34578ac47d 127.0.0.1:6385@16385 slave a435cf98c3444b0b110a224401e397a107c453ef 0 1586620149000 5 connected

自此,RedisCluster已經手動搭建完成。手動搭建可以理解集群建立的流程和細節,不過大家也會發現手動搭建有很多步驟,當集群的節點比較多的時候,肯定會讓人頭大。所以Redis官方提供了redis-trib.rb工具,可以讓我們快速地搭建集群。

自動搭建

redis-trib.rb是使用Ruby開發的Redis Cluster的管理工具,不需要額外下載,預設位於源碼包的src目錄下,但因為該工具是用Ruby開發的,所以需要準備相關的依賴環境。

歡迎關註微信公眾號:萬貓學社,每周一分享Java技術乾貨。

環境準備

安裝Ruby:

yum -y install zlib-devel
wget https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.1.tar.gz
tar xvf ruby-2.5.1.tar.gz
cd ruby-2.5.1/
./configure -prefix=/usr/local/ruby
make
make install
cd /usr/local/ruby/
cp bin/ruby /usr/local/bin
cp bin/gem /usr/local/bin

安裝rubygem redis依賴:

wget http://rubygems.org/downloads/redis-3.3.0.gem
gem install -l redis-3.3.0.gem

安裝redis-trib.rb:

cp src/redis-trib.rb /usr/local/bin

執行redis-trib.rb命令確認一下環境是否準備正確:

# redis-trib.rb help
Usage: redis-trib <command> <options> <arguments ...>

  create          host1:port1 ... hostN:portN
                  --replicas <arg>
  check           host:port
  info            host:port
  fix             host:port
                  --timeout <arg>
  reshard         host:port
                  --from <arg>
...此處省略一萬個字...

搭建集群

像前面的內容講的,準備好節點配置並啟動:

src/redis-server conf/redis-7380.conf &
src/redis-server conf/redis-7381.conf &
src/redis-server conf/redis-7382.conf &
src/redis-server conf/redis-7383.conf &
src/redis-server conf/redis-7384.conf &
src/redis-server conf/redis-7385.conf &

使用redis-trib.rb create命令完成節點握手和槽分配的工作,命令如下:

redis-trib.rb create --replicas 1 127.0.0.1:7380 127.0.0.1:7382 127.0.0.1:7384 127.0.0.1:7381 127.0.0.1:7383 127.0.0.1:7385

其中--replicas 參數用來指定集群中每個主節點有幾個從節點,這裡設置的是1。命令執行後,會首先給出主從節點的分配計劃:

>>> Creating cluster
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
127.0.0.1:7380
127.0.0.1:7382
127.0.0.1:7384
Adding replica 127.0.0.1:7383 to 127.0.0.1:7380
Adding replica 127.0.0.1:7385 to 127.0.0.1:7382
Adding replica 127.0.0.1:7381 to 127.0.0.1:7384
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: c25675d021c377c91f860986025e3779d89ede79 127.0.0.1:7380
   slots:0-5460 (5461 slots) master
M: 58980a81b49de31383802d7d21d6782881678922 127.0.0.1:7382
   slots:5461-10922 (5462 slots) master
M: 3f00a37d2c7a5ea40671c8f2934f66d059157a4a 127.0.0.1:7384
   slots:10923-16383 (5461 slots) master
S: 6f7dd93973a8332305831e6b7b5e2c54c15b3b51 127.0.0.1:7381
   replicates 3f00a37d2c7a5ea40671c8f2934f66d059157a4a
S: 03e01f82a935ed7f977af092e6a9cb71057df68a 127.0.0.1:7383
   replicates c25675d021c377c91f860986025e3779d89ede79
S: 2cf3883e974a709b7070d6c4d7c528d9fa813358 127.0.0.1:7385
   replicates 58980a81b49de31383802d7d21d6782881678922
Can I set the above configuration? (type 'yes' to accept):

如果我們同意這份計劃就輸入yes,之後就會開始執行節點握手和槽分配,輸入如下:

>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join....
>>> Performing Cluster Check (using node 127.0.0.1:7380)
M: c25675d021c377c91f860986025e3779d89ede79 127.0.0.1:7380
   slots:0-5460 (5461 slots) master
   1 additional replica(s)
M: 58980a81b49de31383802d7d21d6782881678922 127.0.0.1:7382
   slots:5461-10922 (5462 slots) master
   1 additional replica(s)
S: 2cf3883e974a709b7070d6c4d7c528d9fa813358 127.0.0.1:7385
   slots: (0 slots) slave
   replicates 58980a81b49de31383802d7d21d6782881678922
S: 03e01f82a935ed7f977af092e6a9cb71057df68a 127.0.0.1:7383
   slots: (0 slots) slave
   replicates c25675d021c377c91f860986025e3779d89ede79
S: 6f7dd93973a8332305831e6b7b5e2c54c15b3b51 127.0.0.1:7381
   slots: (0 slots) slave
   replicates 3f00a37d2c7a5ea40671c8f2934f66d059157a4a
M: 3f00a37d2c7a5ea40671c8f2934f66d059157a4a 127.0.0.1:7384
   slots:10923-16383 (5461 slots) master
   1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

集群創建完成後,還可以使用redis-trib.rb check命令檢查集群是否創建成功,具體命令如下:

# redis-trib.rb check 127.0.0.1:7380
>>> Performing Cluster Check (using node 127.0.0.1:7380)
M: c25675d021c377c91f860986025e3779d89ede79 127.0.0.1:7380
   slots:0-5460 (5461 slots) master
   1 additional replica(s)
M: 58980a81b49de31383802d7d21d6782881678922 127.0.0.1:7382
   slots:5461-10922 (5462 slots) master
   1 additional replica(s)
S: 2cf3883e974a709b7070d6c4d7c528d9fa813358 127.0.0.1:7385
   slots: (0 slots) slave
   replicates 58980a81b49de31383802d7d21d6782881678922
S: 03e01f82a935ed7f977af092e6a9cb71057df68a 127.0.0.1:7383
   slots: (0 slots) slave
   replicates c25675d021c377c91f860986025e3779d89ede79
S: 6f7dd93973a8332305831e6b7b5e2c54c15b3b51 127.0.0.1:7381
   slots: (0 slots) slave
   replicates 3f00a37d2c7a5ea40671c8f2934f66d059157a4a
M: 3f00a37d2c7a5ea40671c8f2934f66d059157a4a 127.0.0.1:7384
   slots:10923-16383 (5461 slots) master
   1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

可以看到,所有的槽都已分配到節點上,大功告成!

微信公眾號:萬貓學社

微信掃描二維碼

獲得更多Java技術乾貨


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 我的MySQL安裝在Linux上,如果我要想在Windows上連接linux上的MySQL,可以使用一些工具,如Navicat和SQLyog。我在這裡用SQLyog演示一下Windows遠程連接MySQL。 第一次連接MySQL 首先安裝SQLyog,這裡就不演示了。打開SQLyog,在菜單欄點擊【 ...
  • 原文地址:http://lefred.be/content/top-10-mysql-8-0-features-for-dbas-ops/ 臨時表的改進 MySQL 5.7中,所有內部臨時表都是在名為“ibtmp1”的惟一共用表空間中創建的。此外,臨時表的元數據也將存儲在記憶體中(不再存儲在.frm文 ...
  • 操作系統:CentOS 7 MySQL版本:5.7.29 通過rpm包方式安裝就像去服裝店買衣服,衣服的大小、顏色等樣式都是設計好的,我們只要買來就能穿,方便快捷。 一、下載rpm包 打開MySQL官網的下載頁面:https://downloads.mysql.com/archives/commun ...
  • 原文地址:https://mysqlserverteam.com/mysql-8-0-innodb-now-supports-instant-add-column/ 長期以來,即時DDL一直是最受歡迎的InnoDB功能之一。對於越來越大且快速增長的數據集,任何網路規模資料庫中必須具備立即執行DDL的 ...
  • 在SparkSQL中Spark為我們提供了兩個新的抽象,分別是DataFrame和DataSet。他們和RDD有什麼區別呢?首先從版本的產生上來看:RDD (Spark1.0) —> Dataframe(Spark1.3) —> Dataset(Spark1.6) 如果同樣的數據都給到這三個數據結構 ...
  • 1.版本選取 訪問mongodb的鏡像倉庫地址:https://hub.docker.com/_/mongo?tab=tags&page=1 這裡選取最新版本進行安裝,如果想安裝其他的可用版本,可以使用命令“docker search mongo”來查看 2.拉取最新版本鏡像 這裡執行命令"sudo ...
  • https://www.cnblogs.com/aspirant/p/9214485.html 一步步分析為什麼B+樹適合作為索引的結構 以及索引原理 mysql的B+樹索引 查找使用了二分查找,redis 跳錶也使用了二分查找法,kafka查詢消息日誌也使用了二分查找法,二分查找法時間複雜度O(l ...
  • 表結構 student(StuId,StuName,StuAge,StuSex) 學生表 teacher(TId,Tname) 教師表 course(CId,Cname,C_TId) 課程表 sc(SId,S_CId,Score) 成績表 問題十:查詢沒有學全所有課的同學的學號、姓名 SELECT ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...