分布式Redis?Cluster集群搭建與Redis基本用法
Redis 集群搭建
Redis 是啥
Redis(全稱 REmote DIctionary Server) 是 NoSQL 型數(shù)據(jù)存儲程序,其使用了內(nèi)存來存儲數(shù)據(jù)結(jié)構(gòu),可以作為數(shù)據(jù)庫、緩存、消息代理使用。
Redis 使用鍵值來映射數(shù)據(jù),其數(shù)據(jù)結(jié)構(gòu)支持 strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs, geospatial indexes 等類型。
集群(Cluster)
Redis 集群的官方文檔:https://redis.io/topics/cluster-tutorial
學(xué)這個的時候,建議別老是百度,還是好好啃一下官方文檔,一點點學(xué)吧。
Redis 支持三種集群模式:
- 主從模式
- Sentinel(哨兵)模式
- Cluster 模式
本章的內(nèi)容包括搭建、測試和操作 Redis Cluster(集群)。
主從模式,一個 Primary,多個 Secondary ,以及副本節(jié)點。
哨兵模式,不會。
Cluster 模式,主要為了提高并發(fā)能力和解決性能瓶頸。
Redis Cluster 說明
Redis Cluster 能夠保證 Redis 服務(wù)一定程度的可用性,當(dāng)集群中一部分實例發(fā)生故障時,其余實例還能正常運行。但是如果發(fā)生較大故障,整個 Redis 集群可能會停止運行。
Redis 集群的每個節(jié)點都需要使用兩個 TCP 端口,一個是常規(guī)提供給客戶端服務(wù)的端口,如 6379;而群集總線需要使用的端口是常規(guī)端口加上 10000 ,例如 73479。
Redis Cluster 不支持 NATted 環(huán)境,也就是不支持 Docker 重新映射端口,如果要在 Docker 上使用 Redis 集群,則需要使用 Dockers
主機(jī)模式,即啟動 Redis 時要附加 --net=host
參數(shù)。
Redis Cluster 中,提供服務(wù)的都是 主節(jié)點(redis-master),從屬節(jié)點(redis-slave) 用于備份主節(jié)點的數(shù)據(jù),當(dāng)主節(jié)點故障時,從屬節(jié)點可以替換主節(jié)點。
Redis Cluster 節(jié)點
Redis 多個 Redis 實例來提供功能,即分片功能,每個 Redis 實例都是主節(jié)點。例如 A、B、C 三個節(jié)點集組成一個完整的 Redis 系統(tǒng),redis cluster 自動將數(shù)據(jù)分片(sharding),在每個節(jié)點上放置一部分?jǐn)?shù)據(jù),這三個節(jié)點都是主節(jié)點。
例如 有 100 條數(shù)據(jù),前 40 條在 A中,剩下的在 B、C中。
沒有 primary,每個主節(jié)點都可以提供服務(wù),這樣就降低了服務(wù)器的壓力,盡量使得流量被多臺節(jié)點平均。要刪除 C ,則將 C 的數(shù)據(jù)分為兩部分,分別推送到 A 和 B 中,這就是數(shù)據(jù)復(fù)制。
但是,如果 C 故障了,那么整個集群則會癱瘓,因為 A、B、C 各自的數(shù)據(jù)是不同的。這就是 Redis Cluster 的缺點。
更多知識,請打開官方文檔了解 https://redis.io/topics/cluster-tutorial
后面使用 & 符號來代表從屬節(jié)點,如 &C,代表 C 的從屬節(jié)點。
Redis Cluster 集群模式
Redis Cluster 集群,每個主節(jié)點有多個從屬節(jié)點,從屬節(jié)點的數(shù)據(jù)于此主節(jié)點一致。
前面提到過如果某一個主節(jié)點故障,將會導(dǎo)致整個集群故障。因此,每個主節(jié)點都應(yīng)該有一個從屬節(jié)點,當(dāng) C 故障時,&C (跟 C 具有一致的數(shù)據(jù))將代替 C 工作。但是如果 C 和 &C 都故障,則整個系統(tǒng)也是會故障的。
Redis Cluster 的工作依賴于 redis.conf 文件。
下面我們將來一步步手動建立集群,過程會比較慢,如果需要盡快建立集群,可以百度找腳本。
為了真實,筆者使用兩臺服務(wù)器搭建服務(wù),共三個主節(jié)點和三個從屬節(jié)點,組成六個節(jié)點群集。
不能保證一致性
當(dāng)客戶端向 C 節(jié)點寫入數(shù)據(jù)時,C 會向 &C 寫入數(shù)據(jù)以保證一致性(同步)。但是這個同步過程是異步的,因為用戶跟 C 交互,完成交互即返回,不可能要用戶等待所有的過程完成,所以 Redis 的設(shè)計是,用戶到 C 是同步,操作后立即返回;而 C 到 &C 是異步的,完全與用戶無關(guān)。
如果客戶端寫入數(shù)據(jù)到 C 后,C 還沒有同步數(shù)據(jù)到 &C,C 就故障了,那么這部分?jǐn)?shù)據(jù)就會丟失。因此這個從屬節(jié)點,并不能保證數(shù)據(jù)的一致性。
創(chuàng)建和使用 Redis 集群
筆者有兩臺服務(wù)器,其理論設(shè)計如下:
服務(wù)器 | 節(jié)點 | port | cluster port |
---|---|---|---|
服務(wù)器1 | A | 7001 | 17001 |
服務(wù)器1 | B | 7002 | 17002 |
服務(wù)器1 | C | 7003 | 17003 |
服務(wù)器2 | &A | 7001 | 17001 |
服務(wù)器2 | &B | 7002 | 17002 |
服務(wù)器2 | &C | 7003 | 17003 |
實際上,由于啟動集群時,節(jié)點是自動分配的,哪個是主節(jié)點哪個是從屬節(jié)點是機(jī)器分配,因此這里只是作為一個設(shè)計思路處理,實際情況要看輸出結(jié)果。
部署三個主節(jié)點
在服務(wù)器 1,創(chuàng)建六個目錄:
mkdir /var/redis cd /var/redis mkdir 7001 7002 7003 A B C
7001、7002、7003 都是以端口命名的,分別存儲 A、B、C 三個節(jié)點的配置文件,而 A、B、C 三個文件是為了使用 Docker 啟動時,映射物理文件(備份數(shù)據(jù))。如果你不是使用 docker 啟動,則不需要 A、B、C 三個目錄。
三個端口目錄分別創(chuàng)建一個 redis.conf 文件,port 的內(nèi)容請根據(jù)端口填寫,其內(nèi)容如下:
port 7001 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes
記得改掉 7001。
如果你只有一臺服務(wù)器,就使用 7001-7006
和 A B C D E F
這這目錄。
非 docker
如果不使用 docker 的話, 可以這樣啟動 redis:
# 命令 redis-server /var/redis/7001/redis.conf # 二進(jìn)制文件 ./redis-server /var/redis/7001/redis.conf # 如法炮制
docker 安裝
如果服務(wù)器的內(nèi)存比較低,例如 1G,2G,則需要執(zhí)行下面的命令,消除 Redis 警告。
查看 /proc/sys/net/core/somaxconn
文件,如果值是 128,則需要修改為 1024。
修改內(nèi)存限制:
echo "vm.overcommit_memory=1" >> /etc/sysctl.conf sysctl vm.overcommit_memory=1
還有一個內(nèi)核問題:
echo never > /sys/kernel/mm/transparent_hugepage/enabled
其它問題請參考這里 解決Redis啟動警告問題
拉取最新 redis 鏡像:
docker pull redis:latest
執(zhí)行以下三個命令啟動三個 redis 實例:
docker run -itd --name redisa --net=host -v /var/redis/A:/data -v /var/redis/7001:/etc/redis redis:latest redis-server /etc/redis/redis.conf --appendonly yes
docker run -itd --name redisb --net=host -v /var/redis/B:/data -v /var/redis/7002:/etc/redis redis:latest redis-server /etc/redis/redis.conf --appendonly yes
docker run -itd --name redisc --net=host -v /var/redis/C:/data -v /var/redis/7003:/etc/redis redis:latest redis-server /etc/redis/redis.conf --appendonly yes
把本小節(jié)的內(nèi)容,在另一臺服務(wù)器上執(zhí)行相同的操作。如果你是一臺服務(wù)器,則也可以在這里修改一下,創(chuàng)建 6 個容器。
命令解析:
--net=host
:使用主機(jī)網(wǎng)絡(luò),這樣就不需要使用 -p 來映射端口了;
-v /var/redis/B:/data
:數(shù)據(jù)持久化;
/var/redis/7002:/etc/redis
:將物理機(jī)目錄映射到容器中,里面有個配置文件;
redis-server
: 啟動容器時執(zhí)行的命令;
/etc/redis/redis.conf
:一個啟動參數(shù),告訴 redis-server
,要使用哪個配置啟動;
--appendonly yes
:總是重啟;
創(chuàng)建集群
如果使用 docker 安裝,則在第一臺服務(wù)器執(zhí)行命令進(jìn)入容器。
docker exec -it redisa bash
然后創(chuàng)建集群:
redis-cli --cluster create {ip}:7001 {ip}:7002 {ip}:7003 {ip}:7001 {ip}:7002 {ip}:7003 --cluster-replicas 1
注:請自行替換 ip 地址。
執(zhí)行命令后,會自動分配 redis 實例的地位,輸入 yes 同意這種分配:
這種自動分配是最優(yōu)的,避免三臺主節(jié)點都在同一臺服務(wù)器中。
集群搭建完畢,我們來開始學(xué)習(xí) Redis 中的一些概念,然后使用 C# 創(chuàng)建程序連接 Redis 。
Redis 入門
Redis 中的數(shù)據(jù)類型
Redis 中,常用的數(shù)據(jù)類型有以下幾種:
- String 字符串
- Hash 散列/哈希
- List 列表
- Set 集合
- Sorted Set 有序集合
所有數(shù)據(jù)都是 key-value 形式存儲,每個數(shù)據(jù)都有唯一的 key,以上數(shù)據(jù)類型是 value。
刪除一個數(shù)據(jù)的命令:DEL {key}
。
字符串(string)
字符串沒啥好說的,就是 value 為 string。
Redis 命令,要設(shè)置或使用字符串類型的數(shù)據(jù),則使用SET
或 GET
開頭的命令:
# 設(shè)置字符串 SET a AAA SET b 666 # 其中 a 是 key,AAA 是 value,不需要 "" 包圍字符串 # ------ # 獲取字符串 GET a # ------ # 獲取多個字符串 MGET a b # 使用空格分隔 key
因為 redis 沒有值類型,因此使用不加 ""
也會被識別為字符串。建議加上雙引號比較好,提高可讀性。
哈希(Hash)
一個 string 類型,是 key-value 結(jié)構(gòu),而哈希則是 {key-value} 的集合,key 是 string 類型,value 可以是其它類型。
因此,可以稱 Hash 為鍵值對的集合,就是相當(dāng)于 C# 中的字典類型,主要存儲有結(jié)構(gòu)的數(shù)據(jù)。
Redis 中每個 hash 可以存儲 232 - 1 個鍵值對(40多億)。
Hash 使用 HMSET
、 HMGET
、HGETALL
等命令來操作哈希表。
有一個這個的數(shù)據(jù):
id:1, name:"癡者工良"
使用哈希存儲:
# HMSET {key} {filed1} {value1} {filed2} {value2} ... ... HMSET user id "1" name "癡者工良"
查詢此哈希表的所有鍵值對:
HGETALL user
查看哈希表的一個字段:
HGET user id
刪除其中一個字段:
HDEL user {字段名稱}
列表(Lists)
列表中可以添加多中類型的元素,簡單的就是字符串,列表即是數(shù)據(jù)結(jié)構(gòu)中的鏈表,使用雙向列表技術(shù)實現(xiàn),越靠近兩側(cè)的元素速度越快。
子元素的添加要從頭部或尾部加入,由于列表是棧,因此列表是有序的。因為列表是有序的,因此可以存儲重復(fù)的數(shù)據(jù)。
適合做例如消息記錄(隊列),粉絲關(guān)注記錄、訂單記錄等。
列表只能添加字符串。
往一個列表加入數(shù)據(jù):
LPUSH {key} {一個元素值}
例如:
LPUSH list a LPUSH list b LPUSH list c
列表的命令比較多,自己查詢文檔就好,這里不再贅述。
集合(Set)
列表(List)是有序的,集合(Set)是無序的。集合不能出現(xiàn)重復(fù)的數(shù)據(jù)。
應(yīng)用場景如網(wǎng)站的訪問IP(去重)記錄、花店中花的種類等。
集合是字符串元素的集合,只能存儲字符串。
使用 SADD
命令往集合中添加一個元素:
SADD set a SADD set b SADD set c SADD set a b c
有序集合(sorted set)
有序集合跟集合一樣,只是有有序集合會根據(jù)元素的值從小到大排序。
有序集合也只能添加字符串。
ZADD ss 2 a ZADD ss 1 b ZADD ss 4 z
查詢:
ZRANGE ss 0 10 WITHSCORES
提醒一下,生產(chǎn)環(huán)境記得給 Redis 設(shè)置密碼。
到此這篇關(guān)于分布式Redis Cluster集群搭建與Redis基本用法的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
詳談redis優(yōu)化配置和redis.conf說明(推薦)
下面小編就為大家?guī)硪黄斦剅edis優(yōu)化配置和redis.conf說明(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-03-03Redis優(yōu)化經(jīng)驗總結(jié)(必看篇)
下面小編就為大家?guī)硪黄猂edis優(yōu)化經(jīng)驗總結(jié)(必看篇)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-03-03