redis 系列26 Cluster高可用 (1)

来源:https://www.cnblogs.com/MrHSR/archive/2018/12/25/10169394.html
-Advertisement-
Play Games

一.概述 Redis集群提供了分散式資料庫方案,集群通過分片來進行數據共用,並提供複製和故障轉移功能。在大數據量方面的高可用方案,cluster集群比Sentinel有優勢。但Redis集群並不支持處理多個keys的命令,因為這需要在不同的節點間移動數據,而達不到像Redis那樣的性能,在高負載的情 ...


一.概述

  Redis集群提供了分散式資料庫方案,集群通過分片來進行數據共用,並提供複製和故障轉移功能。在大數據量方面的高可用方案,cluster集群比Sentinel有優勢。但Redis集群並不支持處理多個keys的命令,因為這需要在不同的節點間移動數據,而達不到像Redis那樣的性能,在高負載的情況下可能會導致不可預料的錯誤。學習集群同樣先瞭解一些原理方麵包括:節點、槽指派、命令執行、重新分片,轉向、故障轉移、消息。後面再操作集群演示。關於集群搭建後面會列出實現步驟,也可參考Redis官網的實現步驟:http://www.redis.cn/topics/cluster-tutorial.html

 

  1.1 節點

    一個Redis集群通常由多個節點(node)組成,開始每個節點都是相互獨立的,需要將獨立的節點連接起來,構成一個包含多節點的集群。連接各節點的工作使用cluster meet命令來完成,格式如下:

        cluster meet ip  port    

    向一個節點發送該命令,可以讓發送的節點與指定的節點進行握手,握手成功時,指定的節點就會添加到發送節點當前所在的集群中。例如:有三個獨立的節點,埠分別為:7000, 7001,7002。首先使用客戶端連接上節點7000, 通過發送cluster nodes命令可以看到,集群目前只包含7000自己一個節點,通過cluster nodes查看信息如下:

    /usr/local/redis/bin
    [root@hsr bin]# ./redis-cli -c -p 7000 -a 123456
    127.0.0.1:7000> cluster nodes
    142116fa16006f39865ebe604d1580c119fa0fea :7000@17000     myself,master - 0 0 0 connected

    通過向節點7000發送以下命令,可以將節點7001 添加到7000所在的集群中:

    127.0.0.1:7000> cluster meet 127.0.0.1 7001
    OK

    繼續向節點7000發送以下命令,可以將節點7002也添加到7000和7001所在的集群中:

    127.0.0.1:7000> cluster meet 127.0.0.1 7002
    OK

    三個節點握手成功,使三個節點都處於同一個集群中,再次查看集群節點情況,三個節點都connected連接成功:

    127.0.0.1:7000> cluster nodes
  0eed9cc9122d2724365550b70965c2a8e281043d 127.0.0.1:7002@17002 master - 0 1545632759414 2 connected
  aeaaeacb8b4d4c4a3bca3c6f52fc4b363e68f083 127.0.0.1:7001@17001 master - 0 1545632758405 0 connected
  142116fa16006f39865ebe604d1580c119fa0fea 127.0.0.1:7000@17000 myself,master - 0 1545632756000 1 connected

     cluster nodes由以下欄位組成,表格如下:

欄位名

描述

節點7002的欄位值

id

節點 ID,一個40個字元的隨機字元串

0eed9cc9122d2724365550b70965c2a8e281043d
ip:port 客戶端應該聯繫節點以運行查詢的節點地址 127.0.0.1:7002
flags 逗號列表分隔的標誌,myself,master,slave,fail等 master
master 如果節點是從屬節點,並且主節點已知,則節點ID為主節點,否則為“ - ”字元 -
ping-sent 毫秒為單位的當前激活的ping發送的unix時間 1545632759414
config-epoch 當前節點的配置時期,每次發生故障切換時,都會創建一個新的,唯一的 2>
link-state 用於節點到節點集群匯流排的鏈路狀態。我們使用此鏈接與節點進行通信 connected
slot 在connected後面還會顯示槽號範圍 分配槽後顯示
    (1)  啟動節點

      一個節點就是一個運行在集群模式下的Redis伺服器,Redis伺服器在啟動時會根據cluster-enabled 配置選項是否為yes來決定是否開啟伺服器的集群模式。每個節點還是與普通redis服務一樣,具備所有功能比如:支持RDB、AOF持久化、發佈與訂閱、保存鍵值對、複製 等等。對於集群模式才會用到的數據,內部保存在cluster.h/clusterState結構中。

    (2) 集群數據結構

      內部clusterNode結構保存了一個節點的當前狀態,比如節點的創建時間、節點的名字、節點當前的配置紀元、節點的IP、Port等等。每個節點都會使用一個clusterNode結構來記錄自己的狀態,併為集群中的所有其它節點(包括主從)都會創建一個相應的clusterNode結構, 以此來記錄其它節點的狀態。該結構中的屬性不再介紹,詳細請查看"redis設計與實現"書。

    (3) cluster meet 命令的實現

    上面講到通過cluster meet 命令,可以使節點與指定的節點進行握手形成集群。假設有節點A和B 握手的步驟包括:

      (1) 在客戶端向節點A發送一條 cluster meet  B命令時,節點A會為節點B創建一個ClusterNode結構,並將該結構添加到自己的ClusterState.nodes字典中。

      (2) 向節點B發送meet後,如果順利節點B將接收到節點A消息,節點B會為節點A創建一個ClusterNode結構, 並將該結構添加到自己的ClusterState.nodes字典中。

      (3) 節點B 將向節點A返回一條PONG消息。

      (4) 節點A接收B返回的消息,能過這條PONG消息節點A知道節點B已經成功接收到了自己發送的MEET消息。

      (5) 節點A將向B返回一條PING消息。

      (6) 節點B將接收A的消息,通過這條PING消息節點B知道節點A已經成功接收到了自己返回的PONG消息,握手成功。

    之後節點A會將節點B的信息通過Gossip協議傳播給集群中的其他節點,讓其他節點也與節點B進行握手,最終節點B會被集群中所有節點認識。

 

  1.2  槽指派 

     Redis集群通過分片的方式來保存資料庫中的鍵值對:集群的整個 資料庫被分為16384個槽(slot), 資料庫中的每個鍵都屬於這16384 個slot其中一個,集群中的每個節點可以處理0個或最多16384個slot。當資料庫中的16384個slot都有在節點中分配時,此時集群處於上線狀態(OK),相反如果任何一個slot沒有得到分配,那麼集群處於下線狀態(fail)。

    在節點7000的客戶端通過cluster info可以查看,因為集群中的三個節點都沒有在處理任何slot,所以處於下線狀態。能過cluster info來查看集群為fail狀態,如下所示:

    127.0.0.1:7000> cluster info
    cluster_state:fail
    cluster_slots_assigned:0
    cluster_slots_ok:0
    cluster_slots_pfail:0
    cluster_slots_fail:0
    cluster_known_nodes:3

    通向節點發送cluster addslots命令,可以將一個或多個slot指派給某節點負責。例如將slot 0 到5000指派給節點7000負責,手動添加槽時,一定要退出redis客戶端,命令如下:

     [root@hsr bin]# ./redis-cli -h 127.0.0.1 -p 7000 -a 123456 cluster addslots {0..5000}
     OK

    在登到redis客戶端,查看集群節點的槽分配情況,可以看到7000節點已分配了0-5000的槽範圍:

    [root@hsr bin]# ./redis-cli -c -p 7000 -a 123456
    127.0.0.1:7000> cluster nodes
  0eed9cc9122d2724365550b70965c2a8e281043d 127.0.0.1:7002@17002 master - 0 1545635637429 2 connected
  aeaaeacb8b4d4c4a3bca3c6f52fc4b363e68f083 127.0.0.1:7001@17001 master - 0 1545635638436 0 connected
  142116fa16006f39865ebe604d1580c119fa0fea 127.0.0.1:7000@17000 myself,master - 0 1545635635000 1 connected 0-5000

    為了讓7000、7001、7002三個節點所在的集群進入上線狀態,繼續將slot  5001~10000指派給節點7001。 將slot 10001~16383指派給7002。當三個cluster addslots 命令都執行後,資料庫中的16383個slot都已經指派給了相應的節點,集群進入上線狀態。

    [root@hsr bin]# ./redis-cli -h 127.0.0.1 -p 7001 -a 123456 cluster addslots {5001..10000}
    OK
    [root@hsr bin]# ./redis-cli -h 127.0.0.1 -p 7002 -a 123456 cluster addslots {10001..16383}
    OK

    此時已經進入集群進入上線狀態:如下所示:

    127.0.0.1:7000> cluster info
    cluster_state:ok
    cluster_slots_assigned:16384
    cluster_slots_ok:16384
    cluster_slots_pfail:0
    cluster_slots_fail:0
    cluster_known_nodes:3
    cluster_size:2
  127.0.0.1:7000> cluster nodes
  a9e82a7870ac31c221a4d13b28ba9897bb12257c 127.0.0.1:7000@17000 myself,master - 0 1545704528000 0 connected 0-5000
  3b10786d21bbeb66e3517e8d3daa3ee2ce16705e 127.0.0.1:7001@17001 master - 0 1545704529806 1 connected 5001-10000
  7bd0cbd26392d1e98ffe9d46ae153c944d8f398d 127.0.0.1:7002@17002 master - 0 1545704529000 2 connected 10001-16383

    一個節點除了會將自己負責處理的slot外,還會將自己的slot數組通過消息發送給集群中的其他節點,以此來告知其他節點自己目前處理哪些slot。例如:當節點A  通過消息從節點B那裡接收到節點B的slot數組時,節點A會在自己的ClusterState.nodes字典中查找節點B對應的ClusterState結構,並對結構中的slots數組進行保存或更新。這樣下來集群中的每個節點都會知道資料庫中的16384個slot分別被指派給了集群中的哪些節點。

    下圖是集群中各節點的ClusterState.nodes字典,裡面記錄了slot與各節點的分配關係:

    

  1.3  在集群中執行命令  

     在對資料庫中的16384個slot都進行了指派之後,集群進入上線狀態,這時客戶端就可以向集群中的節點發送數據命令了。當客戶端向節點發送鍵有關的命令時,接收的節點會計算出命令要處理的鍵屬於哪個slot,並檢查這個slot是否派給了節點自己:

    (1)如果鍵所在的slot正好就指派給了當前節點,那麼節點直接執行這個命令。

    (2)如果鍵所在的slot並沒有指派給當前節點,那麼節點會向客戶端返回一個moved錯誤,指引客戶端轉向到正確的節點,並再次發送之前想要的執行命令。

    自動分配節點和槽號,示例如下所示:

     -- 在節點7000寫入一個鍵值對,發現自動分配到7001的14041槽號中。
     127.0.0.1:7000> set cluster "hello 7000"
     -> Redirected to slot [14041] located at 127.0.0.1:7001
    OK

     --節點7000,讀取該鍵,自動重定向到7001節點中出讀取
     127.0.0.1:7000> get cluster
     -> Redirected to slot [14041] located at 127.0.0.1:7001
     "hello 7000"

      --節點7000, 修改該鍵,自動重定向到7001節點中出修改
    127.0.0.1:7000> set cluster "hello 7001"
    -> Redirected to slot [14041] located at 127.0.0.1:7001
     OK
 
    (1) 計算鍵屬於哪個slot槽

    redis 集群共有16384個哈希槽, 每個key通過CRC16校驗後對16384個槽取模來決定放置到哪個節點的槽號。使用cluster keyslot  key命令可以查看一個指定的鍵屬於哪個slot,例如下麵讀取cluster鍵,對應槽號為14041。如下所示:

    127.0.0.1:7000> cluster keyslot cluster
    (integer) 14041
    (2) moved錯誤(Redirected重定向 )

    當節點發現鍵所在的槽並非由自己負責處理的時候,節點就會向客戶端返回一個moved錯誤,指引客戶端轉向到正在負責槽的節點。moved錯誤格式為:moved slot ip :port。 其中slot為鍵所在的槽,而ip和port則是負責處理槽slot的節點的ip地址和埠號。

    在集群模式下客戶端接收到moved錯誤時,並不會列印出moved錯誤,而是根據moved錯誤自動進行節點轉向,並列印出轉嚮日志Redirected to slot 信息。只有在單機模式下,才會列印moved信息,因為單機模式下的redis-cli客戶端不清楚moved錯誤的作用,所以會直接將moved信息列印出來,則不是進行節點轉向。

    (3) 節點資料庫的實現

    集群節點保存鍵值對以及鍵值對 過期的方式與單機redis服務方式完全相同,節點與單機伺服器在資料庫方面的一個區別是:節點只能使用0號資料庫,而單機redis服務則沒有這一限制。

    

  1.4 重新分片

    Redis集群的重新分片操作可以將任意數量已經指派給某個節點(源節點)的槽改為指派給另一個節點,並且相關槽所屬的鍵值對也會從源節點被移動到目標節點。重新分片操作可以線上online進行,重新分片過程中,集群不需要下線,並且源節點和目標節點都可以繼續處理命令請求。

    例如:在原有節點7000,7001,7002三個節點的集群上,新添加一個節點,埠為7003,然後通過重新分片操作,將原本指派給節點7002的10001~16383的槽,將其中的14042-16383重新分給節點7003。  

    -- 配置好7003的redis.conf, 啟動7003的redis服務    
    [root@hsr cluster-test]# pwd
    /usr/local/redis/cluster-test
    [root@hsr cluster-test]# ./redis-server  ./7003/redis.conf

    -- 將7003加入集群中
    127.0.0.1:7000> cluster meet 127.0.0.1 7003
    OK

    -- 查看集群信息時,有兩個槽(4808,14041)已經自動分配到了7003節點
  127.0.0.1:7000> cluster nodes
  399051ed127fbd1df8a0455858da9c103bf4864a 127.0.0.1:7003@17003 master - 0 1545705387000 3 connected 4808 14041
  a9e82a7870ac31c221a4d13b28ba9897bb12257c 127.0.0.1:7000@17000 myself,master - 0 1545705386000 0 connected 0-4807 4809-5000
  3b10786d21bbeb66e3517e8d3daa3ee2ce16705e 127.0.0.1:7001@17001 master - 0 1545705387741 1 connected 5001-10000
  7bd0cbd26392d1e98ffe9d46ae153c944d8f398d 127.0.0.1:7002@17002 master - 0 1545705387000 2 connected 10001-14040 14042-16383

   通過setslot來簡單演示下重新分配槽:

    在遷移(目的節點)執行cluster setslot <slot> IMPORTING <node ID>命令,指明需要遷移的slot和遷移源節點。

    下麵登錄到7003目的節點,使用cluster setslot將參數14042槽號以及所在的源節點ID,導入到當前7003節點中。

    127.0.0.1:7003> cluster setslot 14042 importing 7bd0cbd26392d1e98ffe9d46ae153c944d8f398d
    OK

    -- 查看cluster nodes ,7003節點信息如下:
    399051ed127fbd1df8a0455858da9c103bf4864a 127.0.0.1:7003@17003 myself,master - 0 1545707846000 3 connected 4808 14041 
[14042-<-7bd0cbd26392d1e98ffe9d46ae153c944d8f398d]

  

  取消遷移操作,可在遷移源節點和遷移目的節點上執行cluster setslot <slot> STABLE下篇介紹使用redis-trib.rb來進行重新分片,redis-trib.rb自動實現了setslot完整的遷移流程。

    


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

-Advertisement-
Play Games
更多相關文章
  • 在使用中,可能我們在建表的時候要用到中文,因此這裡簡單備份下字元集格式;在mysql環境中輸入 可以查看當前連接系統的參數 為了讓mysql資料庫能支持中文,輸入命令 同理把其他的幾個utf8的也改為gbk的然後輸入 這樣,我們在建表的時候就可以使用中文了,趕緊去試試了! ...
  • 本文由雲+社區發表 CynosDB for PostgreSQL是騰訊雲自研的一款雲原生資料庫,其主要核心思想來自於亞馬遜的雲資料庫服務Aurora。這種核心思想就是“基於日誌的存儲”和“存儲計算分離”。同時,CynosDB在架構和工程實現上確實有很多和Aurora不一樣的地方。 下圖為CynosD ...
  • 原文:https://mp.weixin.qq.com/s/-BlLvBKcF-yalELY7XkqaQ 前言 在之前的面試過程中,問到執行計劃,有很多童鞋不知道是什麼?甚至將執行計劃與執行時間認為是同一個概念。今天我們就一起來瞭解一下執行計划到底是什麼?有什麼用途? 執行計劃是什麼? 執行計劃,簡 ...
  • [20181225]12CR2 SQL Plan Directives.txt--//12C引入SQL PLAN Directives.12cR1版本會造成大量的動態取樣,影響性能.許多人把OPTIMIZER_ADAPTIVE_FEATURES設置為false.--//這也是為什麼我不主張將XX.1 ...
  • 前一段時間,由於項目需要將資料庫從SQLServer遷移到MySQL,在網上百度了很久,基本都是通過SQLyog實現的。其實使用平時常用的資料庫管理軟體Navicat Premium也能做到,並且操作簡便。 接下來我介紹一下具體的操作流程 1、首先安裝MySQL和Navicat Premium資料庫 ...
  • 索引的類型 PRIMARY KEY(主鍵索引): 用來標識唯一性,數據不可重覆 ,主鍵列不能為NULL,並且每個表中有且只能有一個主鍵,還可以創建複合主鍵,即多個欄位組合起來。 創建語句為: UNIQUE(唯一性索引):用來限制不受主鍵約束的列上的數據唯一性,一張表種可創建多個唯一性索引。 創建語句 ...
  • 2018/12/24 14:00:57 zabbix監控運行一段時間以後,會留下大量的歷史監控數據,zabbix資料庫一直在增大;可能會造成系統性能下降,查看歷史數據室查詢速度緩慢。 zabbix裡面最大的表就是history和history_uint兩個表,而且zabbix裡面的時間是使用的時間戳 ...
  • 在安裝資料庫軟體時出現以下情況: 解決方法一: 查看 less /uu/oraInventory/ContentsXML/inventory.xml文件,文件內容如下: <?xml version="1.0" standalone="yes" ?><!-- Copyright (c) 1999, 2 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...