關于Redis的集群(上)

目錄

基本概念

數據分片算法

哈希求余

?編輯一致性哈希算法

哈希槽分區算法

搭建集群環境

創建目錄和配置

編寫 docker-compose.yml

啟動容器

構建集群


基本概念

廣義的集群,只要是多個機器構成了分布式系統,都可以成為是一個“集群”。

但是redis提供的集群模式是狹義的集群,這個集群模式之下,主要是解決,存儲空間不足的問題(拓展存儲空間)。

哨兵模式提高了系統的可用性。哨兵模式中本質上還是redis主從節點存儲數據。其中就要求一個主節點/從節點,就得存儲整個數據的“全集”。

此處關鍵問題,就是引入多臺機器,每臺機器存儲一部分數據。每個存儲數據的機器還需要搭配若干個從節點。

每個 Slave 都是對應 Master 的備份(當 Master 掛了, 對應的 Slave 會補位成 Master).
每個紅框部分都可以稱為是?個 分片(Sharding).

把數據分成多份,具體該如何去分呢?


數據分片算法

有三中主流的分片方式。

哈希求余

借鑒了哈希表的基本思想。借助hash函數,把一個key映射到一個數組下標上。再針對數組的長度求余,就可以得到一個數組下標。

比如有三個分片,編號0,1,2。此時就可以針對要插入的數據的key(redis都是鍵值對結構的數據)計算hash值。(比如md5)再把這個hash值余上分片個數,就得到了一個下標。此時就可以把這個數據放到該下標對應的分片中了。

后續查詢key的時候,也是同樣的算法。

拓展:MD5是一個非常廣泛使用的hash算法。

????????特點:1.md5計算結果是定長的。無論輸入的原字符串多長,最終算出的結果就是固定長度。

? ? ? ? ? ? ? ? ? ?2.md5計算結果是分散的。兩個原字符串,哪怕大部分都相同,只有一個小的地方不同,算出來的md5值也會差別很大。

? ? ? ? ? ? ? ? ? ?3.md5計算結果是不可逆的。給你原字符串,可以很容易算出md5的值。給你md5值,很難還原出原始的字符串的。

一旦服務器集群需要擴容,就需要更高的成本。分片主要目的就是為了能提高存儲能力。分片越多,能存的數據越多,成本也更高。隨著業務的增長,數據變多了,需要更多的分片。

當引入更多的分片的時候,N(分片數量)就改變了。如果發現某個數據,在擴容之后,不應該在當前的分片中了,就需要重新進行分配(搬運數據)。絕大部分數據都需要進行搬運,成本過高。

一致性哈希算法

?1)把 0 -> 2^32-1 這個數據空間, 映射到?個圓環上. 數據按照順時針?向增?。

2)假設當前存在三個分?, 就把分?放到圓環的某個位置上。

3)?假定有?個 key, 計算得到 hash 值 H, 那么這個 key 映射到哪個分?呢? 規則很簡單, 就是從 H
所在位置,順時針往下找, 找到的第?個分?, 即為該 key 所從屬的分?。

這就相當于, N 個分?的位置, 把整個圓環分成了 N 個管轄區間。Key 的 hash 值落在某個區間內, 就歸對應區間管理。

此時,如果增加分片,會怎樣呢?

原有分?在環上的位置不動, 只要在環上新安排?個分片位置即可。

此時, 只需要把 0 號分片上的部分數據,搬運給 3 號分片即可。1 號分片和 2 號分片管理的區間都是不變的。

優點: 大大降低了擴容時數據搬運的規模, 提?了擴容操作的效率。
缺點: 數據分配不均勻 (有的多有的少, 數據傾斜)。

哈希槽分區算法

這是redis真正采用的分片算法。采用以下公式:

hash_slot = crc16(key) % 16384

crc16也是一種計算hash的算法,這里不多展開。

16384 = 16* 1024

得到結果hash_slot,稱為哈希槽

會把這些哈希槽分配到不同的分片上。

此時,這三個分片上的數據就是比較均勻的了。會先根據key算出哈希槽,再根據哈希槽,映射到分片。這種算法,本質就是把上述兩種方式結合了一下。

這里只是一種可能的方式,實際上分片是非常靈活的。

每個分片持有的槽位號,可以是連續的,也可以是不連續的。

此時,每個分片都會使用“位圖”這樣的數據結構,表示出當前有多少槽位號。

16384個bit位,用每一位0 / 1來區分自己這個分片當前是否持有該槽位號。??

進行擴容:

上述過程中,只有被移動的槽位,對應的數據才需要搬運。降低了搬運成本。

redis中,當前某個分片包含哪些槽位,都是可以手動配置的。

問題1:Redis集群最多有16384個分片嗎?

如果?個分片只有?個槽位, 這對于集群的數據均勻其實是難以保證的。
實際上 Redis 的作者建議集群分片數不應該超過 1000。而且, 16000 這么?規模的集群, 本?的可用性也是?個?問題. ?個系統越復雜, 出現故障的概率是越?的。

問題2:為什么是16384個槽位?

節點之間通過心跳包通信,心跳包中包含該節點持有那些槽位。如果16384個槽位,每個分片需要2KB大小的位圖,來表示持有的槽位。如果槽位更多,就需要消耗更大的空間,更大的網絡帶寬。16384是比較均衡的值,個數上基本夠用,也不會占據大的硬件資源(網絡帶寬)。


搭建集群環境

這里使用docker來搭建redis集群。

創建目錄和配置

創建 redis-cluster ?錄。內部創建兩個?件。

redis-cluster/
├── docker-compose.yml
└── generate.sh

generate.sh 內容如下:

for port in $(seq 1 9); \
do \
mkdir -p redis${port}/
touch redis${port}/redis.conf
cat << EOF > redis${port}/redis.conf
port 6379
bind 0.0.0.0
protected-mode no
appendonly yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.30.0.10${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
EOF
done
# 注意 cluster-announce-ip 的值有變化.
for port in $(seq 10 11); \
do \
mkdir -p redis${port}/
touch redis${port}/redis.conf
cat << EOF > redis${port}/redis.conf
port 6379
bind 0.0.0.0
protected-mode no
appendonly yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.30.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
EOF
done

在linux上,以.sh后綴結尾的文件,稱為“shell腳本”。使用linux的時候,都是通過一些命令來進行操作的。使用命令操作,就非常適合把命令給寫到一個文件中,批量化執行。同時還能加入條件,循環,函數等機制。就可以基于這些來完成更復雜的工作了。

此時需要創建11個redis節點,這些redis的配置文件內容,大同小異。此時就可以使用腳本來批量生成。

? cluster-enabled yes 開啟集群。
? cluster-config-file nodes.conf 集群節點?成的配置。
? cluster-node-timeout 5000 節點失聯的超時時間。
? cluster-announce-ip 172.30.0.101 節點?? ip。
? cluster-announce-port 6379 節點??的業務端?。
? cluster-announce-bus-port 16379 節點??的總線端?. 集群管理的信息交互是通過這個端口進行的。

編寫 docker-compose.yml

? 先創建 networks, 并分配?段為 172.30.0.0/24
? 配置每個節點. 注意配置?件映射, 端?映射, 以及容器的 ip 地址. 設定成固定 ip ?便后續的觀察和操作。

version: '3.7'
networks:
mynet:
ipam:
config:
- subnet: 172.30.0.0/24
services:
redis1:
image: 'redis:5.0.9'
container_name: redis1
restart: always
volumes:
- ./redis1/:/etc/redis/
ports:
- 6371:6379
- 16371:16379
command:
redis-server /etc/redis/redis.conf
networks:
mynet:
ipv4_address: 172.30.0.101
redis2:
image: 'redis:5.0.9'
container_name: redis2
restart: always
volumes:
- ./redis2/:/etc/redis/
ports:
- 6372:6379
- 16372:16379
command:
redis-server /etc/redis/redis.conf
networks:
mynet:
ipv4_address: 172.30.0.102
redis3:
image: 'redis:5.0.9'
container_name: redis3
restart: always
volumes:
- ./redis3/:/etc/redis/
ports:
- 6373:6379
- 16373:16379
command:
redis-server /etc/redis/redis.conf
networks:
mynet:
ipv4_address: 172.30.0.103

啟動容器

docker-compose up -d

構建集群

接下來,要把上述redis節點構建成集群。

redis-cli --cluster create 172.30.0.101:6379 172.30.0.102:6379
172.30.0.103:6379 172.30.0.104:6379 172.30.0.105:6379 172.30.0.106:6379
172.30.0.107:6379 172.30.0.108:6379 172.30.0.109:6379  --cluster-replicas 2

列出每個參與構建集群的ip和端口。(端口都是容器內部的端口)

cluster create: 表?建?集群. 后?填寫每個節點的 ip 和地址。

cluster-replicas 2: 描述集群的每個主節點,應該有2個從節點。一共9個節點,設置了之后,redis就知道了3個節點是一伙的(一個分片)。

執?之后, 容器之間會進?加?集群操作。?志中會描述哪些是主節點, 哪些從節點跟隨哪個主節點。

>>> Performing hash slots allocation on 9 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 172.30.0.105:6379 to 172.30.0.101:6379
Adding replica 172.30.0.106:6379 to 172.30.0.101:6379
Adding replica 172.30.0.107:6379 to 172.30.0.102:6379
Adding replica 172.30.0.108:6379 to 172.30.0.102:6379
Adding replica 172.30.0.109:6379 to 172.30.0.103:6379
Adding replica 172.30.0.104:6379 to 172.30.0.103:6379

以上,關于redis集群,希望對你有所幫助。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/72635.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/72635.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/72635.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【CSS3】化神篇

目錄 平面轉換平移旋轉改變旋轉原點多重轉換縮放傾斜 漸變線性漸變徑向漸變 空間轉換平移視距旋轉立體呈現縮放 動畫使現步驟animation 復合屬性animation 屬性拆分逐幀動畫多組動畫 平面轉換 作用&#xff1a;為元素添加動態效果&#xff0c;一般與過渡配合使用 概念&#x…

Java 線程創建全解析:五種方式詳細對比與實戰示例

目錄 Java 線程創建全解析&#xff1a;五種方式詳細對比與實戰示例一、引言二、創建線程的五種方式1. 繼承 Thread 類2. 實現 Runnable 接口3. 匿名內部類實現 Thread4. 匿名內部類實現 Runnable5. 使用 Lambda 表達式&#xff08;Java 8及以上&#xff09; 三、線程創建方式對…

Dify平臺離線鏡像部署

Dify 是一款開源的大語言模型(LLM) 應用開發平臺。它融合了后端即服務&#xff08;Backend as Service&#xff09;和 LLMOps 的理念&#xff0c;使開發者可以快速搭建生產級的生成式 AI 應用。即使你是非技術人員&#xff0c;也能參與到 AI 應用的定義和數據運營過程中。 前提…

Unitest和pytest區別

1?? 設計理念 ?? unittest &#xff1a; 是 Python 標準庫的一部分&#xff0c;設計靈感來自 Java 的 JUnit&#xff0c;強調面向對象的測試模式。 測試用例需要繼承 unittest.TestCase 類&#xff0c;測試方法以 test_ 開頭。 更適合傳統、結構化的測試開發方式。 ? pyte…

GIT標簽(Tag)操作

在Git中&#xff0c;標簽&#xff08;Tag&#xff09;用于標記特定的提交點&#xff0c;通常用于發布版本。 切換到需要打標簽的分支&#xff1a; git checkout <branch-name>創建標簽 git tag v1.0.0 git tag -a v1.0.0 -m "Release version 1.0.0"查看所…

玩轉github

me github 可以給倉庫添加開發人員嗎 4o 是的&#xff0c;GitHub允許倉庫管理員為倉庫添加開發人員&#xff0c;并設置這些開發人員的角色和權限。這里是一個簡單的步驟指導&#xff0c;教你如何給一個 GitHub 倉庫添加開發人員&#xff1a; 前提條件 你必須有這個倉庫的權限&…

EDAS:投稿經驗-word版本-問題解決

1. 字體不對&#xff0c;字體未嵌入問題 問題&#xff1a;word轉PDF后&#xff0c;總是顯示有字體格式不對&#xff08;忘記截圖了&#xff09;。 辦法&#xff1a;1. EDAS投稿PDF格式問題-CSDN博客-PDF上修改 IEEE論文檢測的字體未嵌入問題Times New Ro…

如何在Django中有效地使用Celery進行定時任務?

當我們談到Web開發時&#xff0c;Django無疑是一個非常流行的框架。而Celery則是與Django配合使用的強大任務隊列工具。今天&#xff0c;我們來聊聊如何在Django中使用Celery來實現定時任務。定時任務在很多場景下都非常有用&#xff0c;比如定期發送郵件、清理數據庫、執行數據…

聲學建模中用于構音障礙語音識別的特征選擇意義

聲學建模中用于構音障礙語音識別的特征選擇意義 原文:Significance of Feature Selection for Acoustic Modeling in Dysarthric Speech Recognition 引言 背景 構音障礙是由運動言語系統的神經損傷引起的,導致發音不清晰。自動語音識別系統對構音障礙語音無效,因其聲學差…

【遞歸與動態規劃(DP) C/C++】(1)遞歸 與 動態規劃(DP)

- 第 82 篇 - Date: 2025 - 03 - 17 Author: 鄭龍浩/仟濹 【遞歸與動態規劃(DP) C/C】 文章目錄 一 遞歸1基本介紹2 遞歸技巧**(1) 遞歸三步法****(2) 思維小技巧** 3 例題(1) 階乘 (純遞歸 or DP)(2) 斐波那契數列 (純遞歸 or DP)(3) 漢諾塔 (純遞歸 or DP)**① 英文打印過程…

eclipse運行配置,希望帶參數該怎么配置

java -Dparam 在eclipse如何配置 在Eclipse中配置-Dparam這樣的JVM參數&#xff0c;你可以按照以下步驟進行&#xff1a; 打開Eclipse。 選擇菜單欄的"Run" -> "Run Configurations..."。 在彈出的"Run Configurations"窗口左側&#xff0…

什么是 Fisher 信息矩陣

什么是 Fisher 信息矩陣 Fisher 信息矩陣是統計學和機器學習中一個重要的概念,它用于衡量樣本數據所包含的關于模型參數的信息量。 伯努利分布示例 問題描述 假設我們有一個服從伯努利分布的隨機變量 X X X,其概率質量函數為 P ( X 

[C++面試] 標準容器面試點

一、入門 1、vector和list的區別 [C面試] vector 面試點總結 vector 是動態數組&#xff0c;它將元素存儲在連續的內存空間中。支持隨機訪問&#xff0c;即可以通過下標快速訪問任意位置的元素&#xff0c;時間復雜度為 O(1)&#xff0c;準確點是均攤O(1)。但在中間或開頭插…

C++抽象與類的核心概念解析

在C中&#xff0c;抽象&#xff08;Abstraction&#xff09; 是面向對象編程&#xff08;OOP&#xff09;的核心概念之一&#xff0c;它通過隱藏復雜的實現細節&#xff0c;僅暴露必要的接口來實現對現實世界的簡化建模。類&#xff08;Class&#xff09; 是實現抽象的核心工具…

C# NX二次開發:拉伸UFUN函數避坑指南

大家好&#xff0c;今天想說一下拉伸相關UFUN函數的使用&#xff0c;盡量讓大家別踩坑。 官方給出的拉伸UFUN函數有如下幾個&#xff1a; &#xff08;1&#xff09;UF_MODL_create_extruded2 (view source) uf_list_p_tobjectsInputList of objects to be extruded.char *ta…

基于 Python 爬取 TikTok 搜索數據 Tiktok爬蟲(2025.3.17)

1. 前言 在數據分析和網絡爬蟲的應用場景中&#xff0c;我們經常需要獲取社交媒體平臺的數據&#xff0c;例如 TikTok。本篇文章介紹如何使用 Python 爬取 TikTok 用戶搜索數據&#xff0c;并解析其返回的數據。 結果截圖 2. 項目環境準備 在正式運行代碼之前&#xff0c;我…

AI日報 - 2025年3月18日

AI日報 - 2025年3月18日 &#x1f31f; 今日概覽&#xff08;60秒速覽&#xff09; ▎&#x1f916; AGI突破 | SOO微調技術減少語言模型欺騙行為10倍 創新對齊技術為更安全AI鋪路 ▎&#x1f4bc; 商業動向 | Figure推出全球最高產量人形機器人生產線BotQ 年產1.2萬臺&#x…

【go】函數類型的作用

Go 語言函數類型的巧妙應用 函數類型在 Go 語言中非常強大&#xff0c;允許將函數作為值進行傳遞和操作。下面詳細介紹函數類型的各種妙用&#xff1a; 1. 回調函數 // 定義一個函數類型 type Callback func(int) int// 接受回調函數的函數 func processData(data []int, ca…

每日一題--進程與協程的區別

進程是什么&#xff1f; 進程&#xff08;Process&#xff09; 是操作系統進行 資源分配和調度的基本單位&#xff0c;代表一個正在執行的程序實例。每個進程擁有獨立的虛擬地址空間、代碼、數據和系統資源&#xff08;如文件句柄、網絡端口等&#xff09;。進程之間通過 IPC&…

關于deepseek R1模型分布式推理效率分析

1、引言 DeepSeek R1 采用了混合專家&#xff08;Mixture of Experts&#xff0c;MoE&#xff09;架構&#xff0c;包含多個專家子網絡&#xff0c;并通過一個門控機制動態地激活最相關的專家來處理特定的任務 。DeepSeek R1 總共有 6710 億個參數&#xff0c;但在每個前向傳播…