為什麼系統的Swap變高了?(二)
Redis 搭建叢集
我在這裡只記錄點基本內容,不會寫太深入的內容
問題
容量不夠,redis 如何進行擴容?
增加 redis 伺服器,通過叢集解決容量不夠的問題
併發寫操作,redis 如何分攤?
使用叢集負擔寫操作的壓力
主從模式、薪火相傳、主機宕機,都可能導致 ip 地址發生變化,應用程式中配置需要修改對應的主機地址、埠等資訊?
redis 3.0 之前使用代理主機來解決,redis 3.0 中提供瞭解決方案,就是無中心化叢集配置
代理主機方式:
客戶端通過代理伺服器去訪問服務,比如使用者、商品、訂單等服務,每個服務都有從伺服器,代理主機也有從伺服器
無中心化叢集:
每個服務都有從伺服器,但是任何伺服器都可以作為叢集的入口,將服務直接轉移給另外的服務
概念
redis 叢集實現了對 redis 的水平擴容,即啟動 N 個 redis 節點,將整個資料庫分佈儲存在這 N 個節點中,每個節點儲存總資料的 1/N
redis 叢集通過分割槽(partition)來提供一定長度的可用性(availability),即使叢集中有一部分節點失效或者無法進行通訊,叢集也可以繼續處理命令請求
搭建 redis 叢集
我們使用六臺伺服器搭建 redis 叢集,當然,肯定是用一臺機器的不同埠來模擬
步驟:
- 在 redis/bin 目錄建立一個資料夾,例如 cluster
- 我們需要六個 redis 配置,埠號分別為:6379、6380、6381、6389、6390、6391,
6379、6380、6381
6389、6390、6391
是從伺服器 - 配置基本資訊,配置檔名都是 redis_埠號.conf
include cluster/redis.conf
:這是基本的redis配置檔案pidfile /var/run/redis_埠號.pid
port 埠號
dbfilename "dump_埠號.rdb"
cluster-enabled yes:開啟叢集模式
cluster-config-file nodes_埠號.conf
:設定節點配置檔名cluster-node-timeout 15000
:設定節點失聯時間,超過該時間(毫秒),叢集自動進行主從切換
- 啟動六個 redis 服務:開啟三個終端,到 redis/bin 目錄,啟動三臺 redis 伺服器(你也可以給這個命令配置一個環境變數)
./redis-server cluster/redis_6379.conf
./redis-server cluster/redis_6380.conf
./redis-server cluster/redis_6381.conf
./redis-server cluster/redis_6389.conf
./redis-server cluster/redis_6390.conf
./redis-server cluster/redis_6391.conf
- 將六個節點合成一個叢集,組合之前,確保所有 redis 例項啟動後,nodes_埠號.conf 檔案都生成正常(這個 node 檔案在 redis 的 data 目錄下)
- 舊版本的 redis 版本中,需要 ruby 環境
- 比較新的 redis 版本中,不需要額外工具,控制檯進入 redis 原始碼的 src 目錄下,執行命令
redis-cli --cluster create --cluster-replicas 1 ip地址:埠號 ip地址:埠號 ...
,--replicas 1
表示採用最簡單的方式配置叢集,一臺主伺服器,一臺從伺服器。如果有密碼,在後面加-a 密碼
,或者寫配置檔案masterauth 密碼
- 連線要採用叢集策略連線,命令是
./redis-cli -c -h ip地址 -p 埠號
,設定資料會自動切換到相應的主伺服器,連線任意一個伺服器都可以 - 通過
cluster nodes
命令檢視叢集資訊
啟動六個 redis 伺服器
配置叢集,這裡顯示了叢集策略,顯示了哪些伺服器被分配到主伺服器,哪些被分配到從伺服器
輸入 yes 之後就開始建立叢集了,注意,我這裡分配的主從沒有對齊,變成了 6379--6390、6380--6391、6381--6389
,不過這都無所謂,我們繼續
叢集操作
redis cluster 如何分配這六個節點?
一個叢集至少要有三個主節點
選項 --cluster-replicas 1
表示我們希望為叢集中的每個主節點建立一個從節點
分配原則儘量保證每個主資料庫執行在不同的ip地址,每個從資料庫和主資料庫不在一個ip地址上
再看一下 slots
[OK] All 16384 slots covered
,什麼是 slots?
一個 redis 叢集包含 16384 個插槽(hash slot),資料庫中的每個鍵都屬於這 16384 個插槽的其中一個
叢集使用公式 CRC16(key) % 16384
來計算鍵key屬於哪個槽,其中 CRC16(key)
語句用於計算鍵key的 CRC16 校驗和
叢集中的每個節點負責處理一部分插槽,舉個例子,如果一個叢集可以有主節點,其中:
- 節點 A 負責處理 0 號至 5460 號插槽
- 節點 B 負責處理 5461 號至 10922 號插槽
- 節點 C 負責處理 10923 號至 16383 號插槽
但是叢集中任意一臺伺服器都可以作為叢集的入口,所以能互相訪問到自己負責的插槽之外的資料,會直接切換到插槽對應的伺服器
首先我們先用六個 redis-cli 連線對應埠的 redis 服務,一定要用叢集模式連線
三個主伺服器
三個從伺服器
插入資料示例
set name zhangsan
插入資料會自動切換到資料插槽對應的伺服器
查詢資料也會切換到對應的伺服器
從伺服器讀取或寫入資料也會切換過去
但是不能同時使用多條 set 命令,因為插槽算不出來,比如底下這條命令
mset name zhangsan age 20 id 0001
結果會報錯
需要分組,這樣就根據了組的名字去計算插槽的值
mset name{user} zhangsan age{user} 20 id{user} 0001
結果正確
查詢叢集中的值
cluster keyslot <key>
:查詢 key 對應的插槽值cluster countkeysinslot <slot>
:查詢 slot 的值的數量,沒有就是 0 ,只能查詢當前伺服器負責的插槽cluster getkeysinslot <slot> <count>
:返回 count 個 slot 中的 key
故障恢復
如果主節點宕機,從節點自動升為主節點
宕機的主節點重啟之後,這個宕機的主節點會自動變成從節點
如果主從節點都宕機了,根據 redis.conf 的配置,cluster-require-full-coverage
為 yes ,這是預設值,那麼,整個叢集都宕機;而cluster-require-full-coverage
為 no ,那麼該插槽的資料全部都不能使用,也無法儲存
比如我們 shutdown 一個主伺服器,6380 對應的從伺服器是 6391
再去檢視它的從伺服器 6391,變成了主伺服器,沒有問題
再啟動 6380,變成了從伺服器
叢集的優勢
- 實現擴容
- 分攤壓力
- 無中心配置相對簡單
叢集的缺陷
- 多鍵操作是不被支援的
- 多鍵的 redis 事務是不被支援的,lua 指令碼不被支援
- 由於叢集方案出現較晚,很多公司已經採用了其它的叢集方案,而代理或者客戶端分片的方案想要遷移至 redis cluster,需要整體遷移而不是逐步過渡,複雜度較大