Redis(全稱 REmote DIctionary Server) 是 NoSQL 型數據存儲程序,其使用了內存來存儲數據結構,能夠做爲數據庫、緩存、消息代理使用。html
Redis 使用鍵值來映射數據,其數據結構支持 strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs, geospatial indexes 等類型。node
Redis 集羣的官方文檔:https://redis.io/topics/cluster-tutorialredis
學這個的時候,建議別總是百度,仍是好好啃一下官方文檔,一點點學吧。docker
Redis 支持三種集羣模式:shell
本章的內容包括搭建、測試和操做 Redis Cluster(集羣)。數據庫
主從模式,一個 Primary,多個 Secondary ,以及副本節點。緩存
哨兵模式,不會。bash
Cluster 模式,主要爲了提升併發能力和解決性能瓶頸。服務器
Redis Cluster 可以保證 Redis 服務必定程度的可用性,當集羣中一部分實例發生故障時,其他實例還能正常運行。可是若是發生較大故障,整個 Redis 集羣可能會中止運行。網絡
Redis 集羣的每一個節點都須要使用兩個 TCP 端口,一個是常規提供給客戶端服務的端口,如 6379;而羣集總線須要使用的端口是常規端口加上 10000 ,例如 163479。
Redis Cluster 不支持 NATted 環境,也就是不支持 Docker 從新映射端口,若是要在 Docker 上使用 Redis 集羣,則須要使用 Dockers
主機模式,即啓動 Redis 時要附加 --net=host
參數。
Redis Cluster 中,提供服務的都是 主節點(redis-master),從屬節點(redis-slave) 用於備份主節點的數據,當主節點故障時,從屬節點能夠替換主節點。
Redis 多個 Redis 實例來提供功能,即分片功能,每一個 Redis 實例都是主節點。例如 A、B、C 三個節點集組成一個完整的 Redis 系統,redis cluster 自動將數據分片(sharding),在每一個節點上放置一部分數據,這三個節點都是主節點。
例如 有 100 條數據,前 40 條在 A中,剩下的在 B、C中。
沒有 primary,每一個主節點均可以提供服務,這樣就下降了服務器的壓力,儘可能使得流量被多臺節點平均。要刪除 C ,則將 C 的數據分爲兩部分,分別推送到 A 和 B 中,這就是數據複製。
可是,若是 C 故障了,那麼整個集羣則會癱瘓,由於 A、B、C 各自的數據是不一樣的。這就是 Redis Cluster 的缺點。
更多知識,請打開官方文檔瞭解 https://redis.io/topics/cluster-tutorial
後面使用 & 符號來表明從屬節點,如 &C,表明 C 的從屬節點。
Redis Cluster 集羣,每一個主節點有多個從屬節點,從屬節點的數據於此主節點一致。
前面提到過若是某一個主節點故障,將會致使整個集羣故障。所以,每一個主節點都應該有一個從屬節點,當 C 故障時,&C (跟 C 具備一致的數據)將代替 C 工做。可是若是 C 和 &C 都故障,則整個系統也是會故障的。
Redis Cluster 的工做依賴於 redis.conf 文件。
下面咱們未來一步步手動創建集羣,過程會比較慢,若是須要儘快創建集羣,能夠百度找腳本。
爲了真實,筆者使用兩臺服務器搭建服務,共三個主節點和三個從屬節點,組成六個節點羣集。
當客戶端向 C 節點寫入數據時,C 會向 &C 寫入數據以保證一致性(同步)。可是這個同步過程是異步的,由於用戶跟 C 交互,完成交互即返回,並且 C 到 & 的同步&程是異步的,不可能要用戶等待全部的過程完成。
若是客戶端寫入數據到 C 後,C 尚未同步數據到 &C,C 就故障了,那麼這部分數據就會丟失。所以這個從屬節點,並不能保證數據的一致性。
筆者有兩臺服務器,其理論設計以下:
服務器 | 節點 | port | cluster port |
---|---|---|---|
服務器1 | A | 7001 | 17001 |
服務器1 | B | 7002 | 17002 |
服務器1 | C | 7003 | 17003 |
服務器2 | &A | 7001 | 17001 |
服務器2 | &B | 7002 | 17002 |
服務器2 | &C | 7003 | 17003 |
實際上,因爲啓動集羣時,節點是自動分配的,哪一個是主節點哪一個是從屬節點是機器分配,所以這裏只是做爲一個設計思路處理,實際狀況要看輸出結果。
在服務器 1,建立六個目錄:
cd /var mkdir 7001 7002 7003 A B C
700一、700二、7003 都是以端口命名的,分別存儲 A、B、C 三個節點的配置文件,而 A、B、C 三個文件是爲了使用 Docker 啓動時,映射物理文件(備份數據)。若是你不是使用 docker 啓動,則不須要 A、B、C 三個目錄。
三個端口目錄分別建立一個 redis.conf 文件,port 的內容請根據端口填寫,其內容以下:
port 7001 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes
記得改掉 7001。
若是你只有一臺服務器,就使用 7001-7006
和 A B C D E F
這這目錄。
若是不使用 docker 的話, 能夠這樣啓動 redis:
# 命令 redis-server /var/redis/7001/redis.conf # 二進制文件 ./redis-server /var/redis/7001/redis.conf # 如法炮製
若是服務器的內存比較低,例如 1G,2G,則須要執行下面的命令,消除 Redis 警告。
查看 /proc/sys/net/core/somaxconn
文件,若是值是 128,則須要修改成 1024。
修改內存限制:
echo "vm.overcommit_memory=1" >> /etc/sysctl.conf sysctl vm.overcommit_memory=1
還有一個內核問題:
echo never > /sys/kernel/mm/transparent_hugepage/enabled
其它問題請參考這裏 https://blog.csdn.net/a491857321/article/details/52006376
拉取最新 redis 鏡像:
docker pull redis:latest
執行如下三個命令啓動三個 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
把本小節的內容,在另外一臺服務器上執行相同的操做。若是你是一臺服務器,則也能夠在這裏修改一下,建立 6 個容器。
命令解析:
--net=host
:使用主機網絡,這樣就不須要使用 -p 來映射端口了;
-v /var/redis/B:/data
:數據持久化;
/var/redis/7002:/etc/redis
:將物理機目錄映射到容器中,裏面有個配置文件;
redis-server
: 啓動容器時執行的命令;
/etc/redis/redis.conf
:一個啓動參數,告訴 redis-server
,要使用哪一個配置啓動;
--appendonly yes
:老是重啓;
若是使用 docker 安裝,則在第一臺服務器執行命令進入容器。
docker exec -it redisa bash
而後建立集羣:
redis-cli --cluster create {ip}:7001 {ip}:7002 {ip}:7003 {ip}:7001 {ip}:7002 {ip}:7003 --cluster-replicas 1
注:請自行替換 ip 地址。
執行命令後,會自動分配 redis 實例的地位,輸入 yes 贊成這種分配:
這種自動分配是最優的,避免三臺主節點都在同一臺服務器中。
集羣搭建完畢,咱們來開始學習 Redis 中的一些概念,而後使用 C# 建立程序鏈接 Redis 。
Redis 中,經常使用的數據類型有如下幾種:
全部數據都是 key-value 形式存儲,每一個數據都有惟一的 key,以上數據類型是 value。
刪除一個數據的命令:DEL {key}
。
字符串沒啥好說的,就是 value 爲 string。
Redis 命令,要設置或使用字符串類型的數據,則使用SET
或 GET
開頭的命令:
# 設置字符串 SET a AAA SET b 666 # 其中 a 是 key,AAA 是 value,不須要 "" 包圍字符串 # ------ # 獲取字符串 GET a # ------ # 獲取多個字符串 MGET a b # 使用空格分隔 key
由於 redis 沒有值類型,所以使用不加 ""
也會被識別爲字符串。建議加上雙引號比較好,提升可讀性。
一個 string 類型,是 key-value 結構,而哈希則是 {key-value} 的集合,key 是 string 類型,value 能夠是其它類型。
所以,能夠稱 Hash 爲鍵值對的集合,就是至關於 C# 中的字典類型,主要存儲有結構的數據。
Redis 中每一個 hash 能夠存儲 232 - 1 個鍵值對(40多億)。
Hash 使用 HMSET
、 HMGET
、HGETALL
等命令來操做哈希表。
有一個這個的數據:
id:1, name:"癡者工良"
使用哈希存儲:
# HMSET {key} {filed1} {value1} {filed2} {value2} ... ... HMSET user id "1" name "癡者工良"
查詢此哈希表的全部鍵值對:
HGETALL user
查看哈希表的一個字段:
HGET user id
刪除其中一個字段:
HDEL user {字段名稱}
列表中能夠添加多中類型的元素,簡單的就是字符串,列表便是數據結構中的鏈表,使用雙向列表技術實現,越靠近兩側的元素速度越快。
子元素的添加要從頭部或尾部加入,因爲列表是棧,所以列表是有序的。由於列表是有序的,所以能夠存儲重複的數據。
適合作例如消息記錄(隊列),粉絲關注記錄、訂單記錄等。
列表只能添加字符串。
往一個列表加入數據:
LPUSH {key} {一個元素值}
例如:
LPUSH list a LPUSH list b LPUSH list c
列表的命令比較多,本身查詢文檔就好,這裏再也不贅述。
列表(List)是有序的,集合(Set)是無序的。集合不能出現重複的數據。
應用場景如網站的訪問IP(去重)記錄、花店中花的種類等。
集合是字符串元素的集合,只能存儲字符串。
使用 SADD
命令往集合中添加一個元素:
SADD set a SADD set b SADD set c SADD set a b c
有序集合跟集合同樣,只是有有序集合會根據元素的值從小到大排序。
有序集合也只能添加字符串。
ZADD ss 2 a ZADD ss 1 b ZADD ss 4 z
查詢:
ZRANGE ss 0 10 WITHSCORES
提醒一下,生產環境記得給 Redis 設置密碼。