日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

你了解Redis集群中的秘密吗?

發布時間:2024/5/15 数据库 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 你了解Redis集群中的秘密吗? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?前言

今天早上北京地鐵,看見一個正在學習Redis的小姐姐,很優秀

在之前的Redis系列文章中,介紹了Redis的持久化、主從復制以及哨兵機制,主從復制+哨兵機制,既可以解決主master和從slave的解耦合實現多服務器備份數據,又可以通過哨兵機制來解決主宕機之后的主從切換,來實現高可用

但是,上面這種方式仍然有不足,最主要的問題就是**存儲能力受到單機限制,以及無法實現寫操作的負載均衡(寫操作均由主來完成)

在Redis3.0在開始使用引入的分布式存儲方案,即Redis集群cluster, 集群是由多個節點組成的,Redis集群的數據分區在這些節點中,節點分為主節點和從節點,一個集群有多個主節點和從節點,只有主節點負責讀寫請求和集群的維護,而從節點只負責主節點數據和狀態信息的復制

集群的搭建

這一部分我們來一起搭建一個含有6個節點的簡單的集群,三主三從,可以選擇所有節點在同一臺服務器上,也可以選擇不在同一服務器上

這里演示以同一服務器為準,以端口號不同來區分主從,配置從簡,三個主節點端口號為:6001、6002、6003,三個對應從節點端口號為7001、7002、7003,搭建集群大致需要四個步驟:

(1)啟動節點:以集群的模式啟動相應的Redis節點,節點獨立\

(2)節點握手:節點之間握手,形成一個網絡\

(3)分配槽位:將16384個槽位分配給多個主節點

(4)指定從節點:為每一個主節點指定相應的從節點

1、啟動節點

其實啟動集群的節點也是和正常節點一樣的,也是通過redis-server來啟動,但是配置文件需要修改,以集群的方式來啟動,看下配置文件案例

#redis-6001.conf port 6001 cluster-enabled yes cluster-config-file "node-6001.conf" logfile "log-6001.log" dbfilename "dump-6001.rdb" daemonize yes

其中的cluster-enabled和cluster-config-file都是和集群相關的配置;

cluster-enabled配置設置相應的啟動模式是單機模式或者集群模式,如果是yes則為按照集群模式啟動,no則為單機模式

可以通過info server命令來查看服務器信息,然后會看到redis_mode這一項對應的值是cluster,代表集群模式,如果是standalone,則為單機模式;

cluster-config-file則指定了集群配置文件的位置,每個節點在運行的時候維護一個集群配置文件,這和剛剛上面配置文件是不同的,屬于集群特有

每當集群信息發生變化時,集群中的所有節點會將信息更新到集群配置文件中,節點重啟的時候也可以重新讀取該配置文件,獲取到集群的信息

Redis節點啟動的時候,首先檢查是否含有集群配置文件,如果有則使用集群配置文件進行配置啟動,如果沒有則初始化配置并且保存到集群配置文件中,集群配置文件是由節點自動維護更新的,不需要人工維護

我們按照上述代碼塊編輯好配置文件之后,使用正常的 redis-server redis-6001.conf 來啟動redis節點,節點成功啟動之后,返回值的第一項就是節點id,由40個16進制字符組成,節點id只在集群初始化的時候創建一次,然后保存到配置文件中,下一次啟動的時候自動讀取使用該id;

和主從復制篇中runid不同的是,runid是每次重啟都會重新創建,但是節點id只在集群初始化的時候創建一次

2、節點握手

節點啟動之后,是互相獨立的,并不知道其它節點的存在,需要進行節點的握手,才可以把這些節點組成一個網絡,互相知道對方的存在,節點握手使用cluster mett ip port 命令來實現

比如我們現在在端口號為6001上的客戶端上執行cluster meet 127.0.0.1 6002,可以完成6001服務器和6002服務器的握手

同理,我們把其余的6003、7001、7002、7003的節點都握手,這樣6000節點便可以感受到其余五個服務器了,通過節點之間的通信,每個節點也可以感受到其它的節點的存在

3、分配槽位

集群中有16384個槽位,槽是數據管理和遷移的基本單位,當數據庫中的16384個槽位都進行了分配之后,集群處于線程狀態,如果有任意一個槽未進行分配,則集群處于下線狀態,我們可以通過cluster info命令來查看集群的狀態,看到cluster_state的狀態是fail,分配槽使用cluster addslots命令,分配槽給主節點

redis-cli -p 6001cluster addslots {0..5461} redis-cli -p 6002cluster addslots {5462..10922} redis-cli -p 6003cluster addslots {10923..16383}

此時再用cluster info查看集群狀態,處于OK狀態

4、指定主從關系

集群中指定主從關系不再像主從復制那樣使用slaveof命令,而是使用cluster replicate命令,參數是節點的id,就是我們上面提到的節點id,可以通過cluster node來查看節點id

redis-cli -p 8000 cluster replicate 2d87d7708efa6df6feb3b1e0cce081dd8984420d redis-cli -p 8001 cluster replicate f1e370caddac65e23477e098863177ba4387a506 redis-cli -p 8002 cluster replicate 171d843413b3d3d0b63f644b6cf07a467108c214

此時再用cluster node查看節點狀態,可以看到節點的主從關系已經建立,實際上,前三步完成后便可以對外提供服務,但是需要指定相應的從節點之后,集群才可以提供高可用的服務

集群搭建完畢,開始原理部分

集群內部

我們雖然上面搞會了搭建集群,但是我們還不知道關于集群的內部原理部分,內部原理這塊我大體分為數據分區、節點通信、集群狀態三部分來說明

1、數據分區:

數據分區有順序分區,哈希分區等,而哈希分區具有天然的隨機性,集群使用的分區方案便是哈希分區的一種。

衡量數據分區方法好壞的標準有很多,其中比較重要的兩個因素是

  • 數據分布是否均勻
  • 增加或刪減節點對數據分布的影響。

由于哈希的隨機性,哈希分區基本可以保證數據分布均勻,因此在比較哈希分區方案時,重點要看增減節點對數據分布的影響。

哈希分區又可分為哈希取余分區、一致性哈希分區、帶虛擬節點的一致性哈希分區,接下來簡單介紹下

哈希取余分區

哈希取余分區思路非常簡單:計算key的hash值,然后對節點數量進行取余,從而決定數據映射到哪個節點上。

該方案最大的問題是,當新增或刪減節點時,節點數量發生變化,系統中所有的數據都需要重新計算映射關系,引發大規模數據遷移

一致性哈希

將整個哈希值空間組織成一個虛擬的圓環,范圍為0-2^32-1;

對于每個數據,根據key計算hash值,確定數據在環上的位置,然后從此位置沿環順時針行走,找到的第一臺服務器就是其應該映射到的服務器

與哈希取余分區相比,一致性哈希分區將增減節點的影響限制在相鄰節點。

以上圖為例,如果在node1和node2之間增加node5,則只有node2中的一部分數據會遷移到node5;如果去掉node2,則原node2中的數據只會遷移到node4中,只有node4會受影響

一致性哈希分區的主要問題在于,當節點數量較少時,增加或刪減節點,對單個節點的影響可能很大,造成數據的嚴重不平衡。

還是以上圖為例,如果去掉node2,node4中的數據由總數據的1/4左右變為1/2左右,與其他節點相比負載過高

帶虛擬節點的一致性哈希

集群采用的是帶虛擬節點的一致性哈希分區,在redis中這里的虛擬節點被稱為槽(slot),redis被設計為16384個槽。

槽是介于數據和實際節點之間的虛擬概念;每個實際節點包含一定數量的槽,每個槽包含哈希值在一定范圍內的數據。

引入槽以后,數據的映射關系由數據hash->實際節點,變成了數據hash->槽->實際節點,在使用了槽的一致性哈希分區中,槽是數據管理和遷移的基本單位。

槽解耦了數據和實際節點之間的關系,增加或刪除節點對系統的影響很小

舉個簡單例子說明:我們存取的key會根據crc16的算法得出一個結果,然后把結果對 16384 求余數,這樣每個 key 都會對應一個編號在 0-16383 之間的哈希槽,通過這個值,去找到對應的插槽所對應的節點,然后直接自動跳轉到這個對應的節點上進行存取操作

2、節點通信:

節點通信主要是依靠端口號、Gossip協議來完成的

端口號

我們通過哨兵那一篇知道了哨兵系統中,哨兵節點是不存儲數據的,主要是負責控制故障轉移;

而在集群系統中,所有的節點都是存儲數據的,也都參與集群的維護,更像是一個大家庭,大家一起來維護,集群中的每個節點都提供了兩個端口號:

  • 普通端口:即我們在前面指定的端口(6001這些)。普通端口主要用于為客戶端提供服務,在節點間數據遷移時也會使用
  • 集群端口:集群端口是普通端口+10000(10000是固定值,無法改變),如6001節點的集群端口為16001。集群端口只用于節點之間的通信,如搭建集群、增減節點等操作時節點間的通信,為了保證集群可以正常工作,可以關閉本地防火墻,不要使用客戶端連接集群接口

Gossip協議

節點之間通信,主要分為幾種類型:單對單、廣播、Gossip協議幾種類型

單對單,這個應該不用我多嗶嗶;

廣播的話,指的是向集群內所有節點發送消息,優點是集群內所有節點獲得的集群信息是一致的,速度快,缺點是每條消息都要發送給所有節點,消耗帶寬;

Gossip協議,在有限的節點網絡中,每個節點隨機的和部分節點通信(其實并不真隨機,而是根據特定的規則選擇相應的節點),經過看似無序的通信之后每個節點的狀態很快會達到一致

Gossip協議的優點是負載低、去中心化、容錯性高;缺點主要是集群的收斂速度慢。

3、集群狀態:

集群的狀態這個概念是比較廣的,包括集群是否處于上線狀態、集群中有哪些節點、節點是否可達、槽的狀態、節點的主從狀態等

那么,集群狀態的信息是由誰來維護的呢?又是怎樣維護的呢?

集群的狀態是由集群中所有節點共同維護的,向上面說的,每個節點對應著有個集群中的端口號,也會生成相應的集群配置文件;

節點為了存儲集群狀態,最主要的是通過clusterNode和clusterState這兩種結構維護集群,前者是記錄了一個節點的狀態,后者是記錄了集群整體的狀態

clusterNode

clusterNode結構保存了一個節點的當前狀態,包括創建時間、節點id、ip和端口號等。

每個節點都會用一個clusterNode結構記錄自己的狀態,并為集群內所有其他節點都創建一個clusterNode結構來記錄節點狀態

typedef struct clusterNode {//節點創建時間mstime_t ctime;//節點idchar name[REDIS_CLUSTER_NAMELEN];//節點的ip和端口號char ip[REDIS_IP_STR_LEN];int port;//節點標識:整型,每個bit都代表了不同狀態,如節點的主從狀態、是否在線、是否在握手等int flags;//配置紀元:故障轉移時起作用,類似于哨兵的配置紀元uint64_t configEpoch;//槽在該節點中的分布:占用16384/8個字節,16384個比特;每個比特對應一個槽:比特值為1,則該比特對應的槽在節點中;比特值為0,則該比特對應的槽不在節點中unsigned char slots[16384/8];//節點中槽的數量int numslots;…………} clusterNode;

clusterState

clusterState結構保存了在當前節點視角下,集群所處的狀態。主要字段包括:

typedef struct clusterState {//自身節點clusterNode *myself;//配置紀元uint64_t currentEpoch;//集群狀態:在線還是下線int state;//集群中至少包含一個槽的節點數量int size;//哈希表,節點名稱->clusterNode節點指針dict *nodes;//槽分布信息:數組的每個元素都是一個指向clusterNode結構的指針;如果槽還沒有分配給任何節點,則為NULLclusterNode *slots[16384];………… } clusterState;

集群方案的設計

設計集群方案時,至少要考慮以下因素:

  • 數據量和訪問量:估算應用需要的數據量和總訪問量(考慮業務發展,留有冗余),結合每個主節點的容量和能承受的訪問量(可以通過benchmark得到較準確估計),計算需要的主節點數量
  • 高可用要求:根據故障轉移的原理,至少需要3個主節點才能完成故障轉移,且3個主節點不應在同一臺物理機上;每個主節點至少需要1個從節點,且主從節點不應在一臺物理機上;因此高可用集群至少包含6個節點
  • 節點數量限制:Redis官方給出的節點數量限制為1000,主要是考慮節點間通信帶來的消耗。在實際應用中應盡量避免大集群;如果節點數量不足以滿足應用對Redis數據量和訪問量的要求,可以考慮:(1)業務分割,大集群分為多個小集群;(2)減少不必要的數據;(3)調整數據過期策略等
  • 適度冗余:Redis可以在不影響集群服務的情況下增加節點,因此節點數量適當冗余即可,不用太大

從節點服務器內部維護了masterhost、masterport兩個字段,用于保存主節點服務器的IP和端口信息

關于主從復制的問題還有很多,下面我會單獨肝一篇來分析主從復制中存在的問題以及解決辦法

結束語

感謝大家能夠做我最初的讀者和傳播者,請大家相信,只要你給我一

份愛,我終究會還你們一頁情的。

歡迎大家關注我的公眾號【左耳君】,探索技術,分享生活

哦對了,后續所有的文章都會更新到這里

https://github.com/DayuMM2021/Java

總結

以上是生活随笔為你收集整理的你了解Redis集群中的秘密吗?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。