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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Docker-redis集群+混合持久化

發布時間:2024/3/24 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Docker-redis集群+混合持久化 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

了解Reids集群三種模式

主從復制模式

通過持久化功能,Redis保證了即使在服務器重啟的情況下也不會丟失(或少量丟失)數據,因為持久化會把內存中數據保存到硬盤上,重啟會從硬盤上加載數據。 但是由于數據是存儲在一臺服務器上的,如果這臺服務器出現硬盤故障等問題,也會導致數據丟失。

為了避免單點故障,通常的做法是將數據庫復制多個副本以部署在不同的服務器上,這樣即使有一臺服務器出現故障,其他服務器依然可以繼續提供服務。

為此, Redis 提供了復制(replication)功能,可以實現當一臺數據庫中的數據更新后,自動將更新的數據同步到其他數據庫上。

在復制的概念中,數據庫分為兩類,一類是主數據庫(master),另一類是從數據庫(slave)。主數據庫可以進行讀寫操作,當寫操作導致數據變化時會自動將數據同步給從數據庫。而從數據庫一般是只讀的,并接受主數據庫同步過來的數據。一個主數據庫可以擁有多個從數據庫,而一個從數據庫只能擁有一個主數據庫。

總結:引入主從復制機制的目的有兩個

  • 一個是讀寫分離,分擔 “master” 的讀寫壓力
  • 一個是方便做容災恢復

主從復制原理

  • 從數據庫啟動成功后,連接主數據庫,發送 SYNC 命令;
  • 主數據庫接收到 SYNC 命令后,開始執行 BGSAVE 命令生成 RDB 文件并使用緩沖區記錄此后執行的所有寫命令;
  • 主數據庫 BGSAVE 執行完后,向所有從數據庫發送快照文件,并在發送期間繼續記錄被執行的寫命令;
  • 從數據庫收到快照文件后丟棄所有舊數據,載入收到的快照;
  • 主數據庫快照發送完畢后開始向從數據庫發送緩沖區中的寫命令;
  • 從數據庫完成對快照的載入,開始接收命令請求,并執行來自主數據庫緩沖區的寫命令;(從數據庫初始化完成)
  • 主數據庫每執行一個寫命令就會向從數據庫發送相同的寫命令,從數據庫接收并執行收到的寫命令(從數據庫初始化完成后的操作)
  • 出現斷開重連后,2.8之后的版本會將斷線期間的命令傳給重數據庫,增量復制。
  • 主從剛剛連接的時候,進行全量同步;全同步結束后,進行增量同步。當然,如果有需要,slave 在任何時候都可以發起全量同步。Redis 的策略是,無論如何,首先會嘗試進行增量同步,如不成功,要求從機進行全量同步。

主從復制優缺點

主從復制優點
  • 支持主從復制,主機會自動將數據同步到從機,可以進行讀寫分離;
  • 為了分載 Master 的讀操作壓力,Slave 服務器可以為客戶端提供只讀操作的服務,寫服務仍然必須由Master來完成;
  • Slave 同樣可以接受其它 Slaves 的連接和同步請求,這樣可以有效的分載 Master 的同步壓力;
  • Master Server 是以非阻塞的方式為 Slaves 提供服務。所以在 Master-Slave 同步期間,客戶端仍然可以提交查詢或修改請求;
  • Slave Server 同樣是以非阻塞的方式完成數據同步。在同步期間,如果有客戶端提交查詢請求,Redis則返回同步之前的數據;
主從復制缺點
  • Redis不具備自動容錯和恢復功能,主機從機的宕機都會導致前端部分讀寫請求失敗,需要等待機器重啟或者手動切換前端的IP才能恢復(也就是要人工介入);
  • 主機宕機,宕機前有部分數據未能及時同步到從機,切換IP后還會引入數據不一致的問題,降低了系統的可用性;
  • 如果多個 Slave 斷線了,需要重啟的時候,盡量不要在同一時間段進行重啟。因為只要 Slave 啟動,就會發送sync 請求和主機全量同步,當多個 Slave 重啟的時候,可能會導致 Master IO 劇增從而宕機。
  • Redis 較難支持在線擴容,在集群容量達到上限時在線擴容會變得很復雜;

哨兵模式(Sentinel)

第一種主從同步/復制的模式,當主服務器宕機后,需要手動把一臺從服務器切換為主服務器,這就需要人工干預,費事費力,還會造成一段時間內服務不可用。這不是一種推薦的方式,更多時候,我們優先考慮哨兵模式。

哨兵模式是一種特殊的模式,首先 Redis 提供了哨兵的命令,哨兵是一個獨立的進程,作為進程,它會獨立運行。其原理是哨兵通過發送命令,等待Redis服務器響應,從而監控運行的多個 Redis 實例。

哨兵模式的作用

  • 通過發送命令,讓 Redis 服務器返回監控其運行狀態,包括主服務器和從服務器;
  • 當哨兵監測到 master 宕機,會自動將 slave 切換成 master ,然后通過發布訂閱模式通知其他的從服務器,修改配置文件,讓它們切換主機;

然而一個哨兵進程對Redis服務器進行監控,也可能會出現問題,為此,我們可以使用多個哨兵進行監控。各個哨兵之間還會進行監控,這樣就形成了多哨兵模式。

故障切換的過程

假設主服務器宕機,哨兵1先檢測到這個結果,系統并不會馬上進行 failover 過程,僅僅是哨兵1主觀的認為主服務器不可用,這個現象成為主觀下線。當后面的哨兵也檢測到主服務器不可用,并且數量達到一定值時,那么哨兵之間就會進行一次投票,投票的結果由一個哨兵發起,進行 failover 操作。切換成功后,就會通過發布訂閱模式,讓各個哨兵把自己監控的從服務器實現切換主機,這個過程稱為客觀下線。這樣對于客戶端而言,一切都是透明的。

哨兵模式的工作方式:

  • 每個Sentinel(哨兵)進程以每秒鐘一次的頻率向整個集群中的 Master 主服務器,Slave 從服務器以及其他Sentinel(哨兵)進程發送一個 PING 命令。
  • 如果一個實例(instance)距離最后一次有效回復 PING 命令的時間超過 down-after-milliseconds 選項所指定的值, 則這個實例會被 Sentinel(哨兵)進程標記為主觀下線(SDOWN)
  • 如果一個 Master 主服務器被標記為主觀下線(SDOWN),則正在監視這個 Master 主服務器的所有 Sentinel(哨兵)進程要以每秒一次的頻率確認 Master 主服務器的確進入了主觀下線狀態
  • 當有足夠數量的 Sentinel(哨兵)進程(大于等于配置文件指定的值)在指定的時間范圍內確認 Master 主服務器進入了主觀下線狀態(SDOWN), 則 Master 主服務器會被標記為客觀下線(ODOWN)
  • 在一般情況下, 每個 Sentinel(哨兵)進程會以每 10 秒一次的頻率向集群中的所有 Master 主服務器、Slave 從服務器發送 INFO 命令。
  • 當 Master 主服務器被 Sentinel(哨兵)進程標記為客觀下線(ODOWN)時,Sentinel(哨兵)進程向下線的 Master 主服務器的所有 Slave 從服務器發送 INFO 命令的頻率會從 10 秒一次改為每秒一次。
  • 若沒有足夠數量的 Sentinel(哨兵)進程同意 Master主服務器下線, Master 主服務器的客觀下線狀態就會被移除。若 Master 主服務器重新向 Sentinel(哨兵)進程發送 PING 命令返回有效回復,Master主服務器的主觀下線狀態就會被移除。

哨兵模式的優缺點

優點:

  • 哨兵模式是基于主從模式的,所有主從的優點,哨兵模式都具有。
  • 主從可以自動切換,系統更健壯,可用性更高(可以看作自動版的主從復制)。

缺點:

  • Redis較難支持在線擴容,在集群容量達到上限時在線擴容會變得很復雜。

集群模式(Cluster)—Redis官方

Redis Cluster是一種服務器 Sharding 技術,3.0版本開始正式提供。

Redis 的哨兵模式基本已經可以實現高可用,讀寫分離 ,但是在這種模式下每臺 Redis 服務器都存儲相同的數據,很浪費內存,所以在 redis3.0上加入了 Cluster 集群模式,實現了 Redis 的分布式存儲,也就是說每臺 Redis 節點上存儲不同的內容。

在這個圖中,每一個藍色的圈都代表著一個 redis 的服務器節點。它們任何兩個節點之間都是相互連通的。客戶端可以與任何一個節點相連接,然后就可以訪問集群中的任何一個節點。對其進行存取和其他操作。

集群的數據分片

Redis 集群沒有使用一致性 hash,而是引入了哈希槽【hash slot】的概念。

Redis 集群有16384 個哈希槽,每個 key 通過 CRC16 校驗后對 16384 取模來決定放置哪個槽。集群的每個節點負責一部分hash槽,舉個例子,比如當前集群有3個節點,那么:

  • 節點 A 包含 0 到 5460 號哈希槽
  • 節點 B 包含 5461 到 10922 號哈希槽
  • 節點 C 包含 10923 到 16383 號哈希槽

這種結構很容易添加或者刪除節點。比如如果我想新添加個節點 D , 我需要從節點 A, B, C 中得部分槽到 D 上。如果我想移除節點 A ,需要將 A 中的槽移到 B 和 C 節點上,然后將沒有任何槽的 A 節點從集群中移除即可。由于從一個節點將哈希槽移動到另一個節點并不會停止服務,所以無論添加刪除或者改變某個節點的哈希槽的數量都不會造成集群不可用的狀態。

在 Redis 的每一個節點上,都有這么兩個東西,一個是插槽(slot),它的的取值范圍是:0-16383。還有一個就是 cluster,可以理解為是一個集群管理的插件。當我們的存取的 Key到達的時候,Redis 會根據 CRC16 的算法得出一個結果,然后把結果對 16384 求余數,這樣每個 key 都會對應一個編號在 0-16383 之間的哈希槽,通過這個值,去找到對應的插槽所對應的節點,然后直接自動跳轉到這個對應的節點上進行存取操作。

Redis 集群的主從復制模型

為了保證高可用,redis-cluster集群引入了主從復制模型,一個主節點對應一個或者多個從節點,當主節點宕機的時候,就會啟用從節點。當其它主節點 ping 一個主節點 A 時,如果半數以上的主節點與 A 通信超時,那么認為主節點 A 宕機了。如果主節點 A 和它的從節點 A1 都宕機了,那么該集群就無法再提供服務了。

集群的特點

  • 所有的 redis 節點彼此互聯(PING-PONG機制),內部使用二進制協議優化傳輸速度和帶寬。
  • 節點的 fail 是通過集群中超過半數的節點檢測失效時才生效。
  • 客戶端與 Redis 節點直連,不需要中間代理層.客戶端不需要連接集群所有節點,連接集群中任何一個可用節點即可。

Docker-redis集群+混合持久化搭建

redis_version:6.0.6 (2020年09月02日14:29:59)

安裝docker-ce

yum install -y yum-utils device-mapper-persistent-data lvm2 yum-config-manager \--add-repo \https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 更新yum軟件源緩存 yum makecache fast yum -y install docker-ce # 開機自啟動 systemctl enable docker systemctl start docker

定義安裝目錄

? 自定義

自定義redis配置文件

? 官方最新配置文件(6.0.7)

? https://github.com/redis/redis/blob/unstable/redis.conf

? 自定義配置6個redis配置文件

# 搭建3主3從 共6節點 for port in $(seq 7002 7007);do;mkdir -p node-${port}/{conf,data} touch node-${port}/conf/redis.conf cat << EOF >node-${port}/conf/redis.conf ##節點端口 port 6379 ##允許任何來源 bind 0.0.0.0 ## 是為了禁止公網訪問redis cache,加強redis安全的。它啟用的條件,有兩個:1) 沒有bind IP 2) 沒有設置訪問密碼 啟用后只能夠通過lookback ip(127.0.0.1)訪問Redis cache,如果從外網訪問,則會返回相應的錯誤信息 protected-mode no ##cluster集群模式 cluster-enabled yes ##用來保存集群狀態信息,可以自定義配置名。 cluster-config-file nodes.conf ## 如果要最大的可用性,值設置為0。定義slave和master失聯時長的倍數,如果值為0,則只要失聯slave總是嘗試failover,而不管與master失聯多久。-----如果不加該參數,集群中的節點宕機后不會進行高可用恢復!!!!! cluster-replica-validity-factor 0 # 定義slave多久(秒)ping一次master,如果超過repl-timeout指定的時長都沒有收到響應,則認為master掛了 repl-ping-replica-period 1 ##超時時間 cluster-node-timeout 5000 ##節點映射端口 cluster-announce-port 6379 ##節點總線端口 cluster-announce-bus-port 16379 ##實際為各節點網卡分配ip #cluster-announce-ip 192.168.XX.XX ##redis密碼 requirepass China ##表示m秒內數據集存在n次修改時,自動觸發bgsave ## 手動執行save該命令會阻塞當前Redis服務器,執行save命令期間,Redis不能處理其他命令,直到RDB過程完成為止。 ## 顯然該命令對于內存比較大的實例會造成長時間阻塞,這是致命的缺陷,為了解決此問題,Redis提供了第二種方式----bgsave ## 執行bgsave命令時,Redis會在后臺異步進行快照操作,快照同時還可以響應客戶端請求。具體操作是Redis進程執行fork操作創建子進程,RDB持久化過程由子進程負責,完成后自動結束。阻塞只發生在fork階段,一般時間很短。 ## 基本上 Redis 內部所有的RDB操作都是采用 bgsave 命令。 ## 執行執行 flushall 命令,也會產生dump.rdb文件,但里面是空的. #關閉RDB功能的話,配置這個即可以,其他save要注釋掉 #save 300 10 save "" ##它是數據文件。當采用快照模式備份(持久化)時,Redis 將使用它保存數據,將來可以使用它恢復數據。 #dbfilename dump.rdb ##持久化模式 appendonly yes #appendfilename appendonly.aof aof-use-rdb-preamble yes # 文件達到64m時進行重寫,然后如果文件大小增長了一倍,也會觸發重寫。 auto-aof-rewrite-min-size 64mb auto-aof-rewrite-percentage 100 ##AOF 文件和 Redis 命令是同步頻率的,假設配置為 always,其含義為當 Redis 執行命令的時候,則同時同步到 AOF 文件,這樣會使得 Redis 同步刷新 AOF 文件,造成緩慢。而采用 evarysec 則代表 ## 每秒同步一次命令到 AOF 文件。 appendfsync everysec pidfile redis.pid # 后臺運行 ---- docker中使用后臺運行將無法啟動容器(應該是容器無法檢測后臺運行進程) # daemonize yes EOF # 修改第一個匹配到的port 6379 為 port $port sed -i "0,/port 6379/s//port $port/" node-${port}/conf/redis.conf sed -i "0,/announce-port 6379/s//announce-port $port/" node-${port}/conf/redis.conf sed -i "0,/bus-port 16379/s//bus-port 1$port/" node-${port}/conf/redis.conf done

安裝docker-redis

鏡像版本版本可以自己修改

# 創建用于redis集群的虛擬網卡(也可以自定義子網) docker network create redis-net # 查看網關IP1 docker network inspect redis-net | grep "Gateway" | grep --color=auto -P '(\d{1,3}.){3}\d{1,3}' -o # 查看網關IP2 docker network inspect redis-net | grep "Gateway" # 運行節點容器 for port in `seq 7002 7007`; do docker run -it -p ${port}:${port} \ --restart always \ --name=redis-${port} \ --net redis-net \ --privileged=true \ -v `pwd`/node-${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf \ -v `pwd`/node-${port}/data:/data \ -d redis:latest redis-server /usr/local/etc/redis/redis.conf; done # 查看redis運行情況 docker ps -a |grep redis

建立Redis集群

  • 查看各個redisIP

    docker network inspect redis-net | grep -E "IPv4Address|Name"
  • 返回結果

    "Name": "redis-net","Name": "redis-6385","IPv4Address": "172.18.0.7/16","Name": "redis-6382","IPv4Address": "172.18.0.4/16","Name": "redis-6380","IPv4Address": "172.18.0.2/16","Name": "redis-6383","IPv4Address": "172.18.0.5/16","Name": "redis-6381","IPv4Address": "172.18.0.3/16","Name": "redis-6384","IPv4Address": "172.18.0.6/16",
  • 進入redis-7007節點創建集群,返回提示信息后,輸入yes

    # 進入docker redis-7007 docker exec -it $(docker ps -qn 1) bash # 創建集群 redis-cli -p 7007 --cluster create 172.18.0.2:7002 172.18.0.3:7003 172.18.0.4:7004 172.18.0.5:7005 172.18.0.6:7006 172.18.0.7:7007 -a China --cluster-replicas 1

查看集群

  • 查看集群狀態

    redis-cli -c -p 7007 -a China cluster info
  • 返回結果

    Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:6 cluster_size:3 cluster_current_epoch:6 cluster_my_epoch:2 cluster_stats_messages_ping_sent:566 cluster_stats_messages_pong_sent:568 cluster_stats_messages_meet_sent:1 cluster_stats_messages_sent:1135 cluster_stats_messages_ping_received:568 cluster_stats_messages_pong_received:567 cluster_stats_messages_received:1135
  • 查看集群各個節點信息

    redis-cli -c -p 7007 -a China cluster nodes
  • 返回結果

    Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 76b5c213dfcb8112c4270db8deadd9faced1189f 172.18.0.7:6379@16379 myself,slave e3092bff97ffea51806dafc7031450ffb1195129 0 1598411316000 2 connected a35caec7a5e3fe8631f006752565063ea9354785 172.18.0.4:6379@16379 master - 0 1598411317000 3 connected 10923-16383 89c88b527dec0e531c83dbd095bac00d88d33c39 172.18.0.6:6379@16379 slave 1e40c530cc4d1b4cc52cbfc9ed9efe52ef28fb72 0 1598411316072 1 connected e3092bff97ffea51806dafc7031450ffb1195129 172.18.0.3:6379@16379 master - 0 1598411317000 2 connected 5461-10922 7438a2db04ec7a97094c2b8a4542d7c68b847008 172.18.0.5:6379@16379 slave a35caec7a5e3fe8631f006752565063ea9354785 0 1598411317584 3 connected 1e40c530cc4d1b4cc52cbfc9ed9efe52ef28fb72 172.18.0.2:6379@16379 master - 0 1598411316000 1 connected 0-5460

Dokcer-redis集群新增節點

自定義redis配置文件

? 配置6個redis配置文件

for port in $(seq 7008 7009);do; mkdir -p node-${port}/{conf,data} touch node-${port}/conf/redis.conf cat << EOF >node-${port}/conf/redis.conf ##節點端口 port 6379 ##允許任何來源 bind 0.0.0.0 ## 是為了禁止公網訪問redis cache,加強redis安全的。它啟用的條件,有兩個:1) 沒有bind IP 2) 沒有設置訪問密碼 啟用后只能夠通過lookback ip(127.0.0.1)訪問Redis cache,如果從外網訪問,則會返回相應的錯誤信息 protected-mode no ##cluster集群模式 cluster-enabled yes ##用來保存集群狀態信息,可以自定義配置名。 cluster-config-file nodes.conf ## 如果要最大的可用性,值設置為0。定義slave和master失聯時長的倍數,如果值為0,則只要失聯slave總是嘗試failover,而不管與master失聯多久。-----如果不加該參數,集群中的節點宕機后不會進行高可用恢復!!!!! cluster-replica-validity-factor 0 # 定義slave多久(秒)ping一次master,如果超過repl-timeout指定的時長都沒有收到響應,則認為master掛了 repl-ping-replica-period 1 ##超時時間 cluster-node-timeout 5000 ##節點映射端口 cluster-announce-port 6379 ##節點總線端口 cluster-announce-bus-port 16379 ##實際為各節點網卡分配ip #cluster-announce-ip 192.168.XX.XX ##redis密碼 requirepass China ##表示m秒內數據集存在n次修改時,自動觸發bgsave ## 手動執行save該命令會阻塞當前Redis服務器,執行save命令期間,Redis不能處理其他命令,直到RDB過程完成為止。 ## 顯然該命令對于內存比較大的實例會造成長時間阻塞,這是致命的缺陷,為了解決此問題,Redis提供了第二種方式----bgsave ## 執行bgsave命令時,Redis會在后臺異步進行快照操作,快照同時還可以響應客戶端請求。具體操作是Redis進程執行fork操作創建子進程,RDB持久化過程由子進程負責,完成后自動結束。阻塞只發生在fork階段,一般時間很短。 ## 基本上 Redis 內部所有的RDB操作都是采用 bgsave 命令。 ## 執行執行 flushall 命令,也會產生dump.rdb文件,但里面是空的. #關閉RDB功能的話,配置這個即可以,其他save要注釋掉 #save 300 10 save "" ##它是數據文件。當采用快照模式備份(持久化)時,Redis 將使用它保存數據,將來可以使用它恢復數據。 #dbfilename dump.rdb ##持久化模式 appendonly yes #appendfilename appendonly.aof aof-use-rdb-preamble yes # 文件達到64m時進行重寫,然后如果文件大小增長了一倍,也會觸發重寫。 auto-aof-rewrite-min-size 64mb auto-aof-rewrite-percentage 100 ##AOF 文件和 Redis 命令是同步頻率的,假設配置為 always,其含義為當 Redis 執行命令的時候,則同時同步到 AOF 文件,這樣會使得 Redis 同步刷新 AOF 文件,造成緩慢。而采用 evarysec 則代表 每秒同步一次命令到 AOF 文件。 appendfsync everysec pidfile redis.pid # 后臺運行 ---- docker中使用后臺運行將無法啟動容器(應該是容器無法檢測后臺運行進程) # daemonize yes EOF # 修改第一個匹配到的port 6379 為 port $port sed -i "0,/port 6379/s//port $port/" node-${port}/conf/redis.conf sed -i "0,/announce-port 6379/s//announce-port $port/" node-${port}/conf/redis.conf sed -i "0,/bus-port 16379/s//bus-port 1$port/" node-${port}/conf/redis.conf done

運行新增節點容器

# 運行節點容器 for port in `seq 7008 7009`; do docker run -it -p ${port}:${port} \ --restart always \ --name=redis-${port} \ --net redis-net \ --privileged=true \ -v `pwd`/node-${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf \ -v `pwd`/node-${port}/data:/data \ -d redis:latest redis-server /usr/local/etc/redis/redis.conf; done

登陸redis7007 新增節點

新增主節點

# 登陸redis7007 docker exec -it redis-7007 bash # 新增主節點 # 說明:為一個指定集群添加節點,需要先連到該集群的任意一個節點IP(172.18.0.7:7007),再把新節點加入。該2個參數的順序有要求:新加入的節點放前 redis-cli -c -a China --cluster add-node 172.18.0.8:7008 172.18.0.7:7007

提示添加成功

root@c9f5ce54a903:/data# redis-cli -c -p 7007 -a China --cluster add-node 172.18.0.8:7008 172.18.0.7:7007 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. >>> Adding node 172.18.0.9:7009 to cluster 172.18.0.7:7007 >>> Performing Cluster Check (using node 172.18.0.7:7007) S: a1dc21e356f983ce8f6af9ffd63e5819f6168f34 172.18.0.7:7007slots: (0 slots) slavereplicates 4a6116ea0bd3e13e603fc93a96e639b1b257e873 M: 4a6116ea0bd3e13e603fc93a96e639b1b257e873 172.18.0.3:7003slots:[5461-10922] (5462 slots) master1 additional replica(s) M: 9d257e1f3be993ab6cc418bee526ad8833e1b371 172.18.0.4:7004slots:[10923-16383] (5461 slots) master1 additional replica(s) M: 5ae566444b78ebc3d077c4fb7f17578b9725045f 172.18.0.2:7002slots:[0-5460] (5461 slots) master1 additional replica(s) M: 16a5ada35a648750daabdb91afa54ba6c62a26c4 172.18.0.8:7008slots: (0 slots) master S: 149b52decbb11b3fbf4199e97da5058bfae4af15 172.18.0.5:7005slots: (0 slots) slavereplicates 9d257e1f3be993ab6cc418bee526ad8833e1b371 S: aa7977e699159e0042a2cec003e4e163ed8c6af2 172.18.0.6:7006slots: (0 slots) slavereplicates 5ae566444b78ebc3d077c4fb7f17578b9725045f [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. >>> Send CLUSTER MEET to node 172.18.0.9:7009 to make it join the cluster. [OK] New node added correctly.

新增從節點

# 新增從節點 # 16a5ada35a648750daabdb91afa54ba6c62a26c4 是主節點的 Node-ID 如果不指定 --cluster-master-id 會隨機分配到任意一個主節點。 redis-cli -c -a China --cluster add-node 172.18.0.9:7009 172.18.0.7:7007 --cluster-slave --cluster-master-id 16a5ada35a648750daabdb91afa54ba6c62a26c4

提示添加成功

root@c9f5ce54a903:/data# redis-cli -c -a China --cluster add-node 172.18.0.9:7009 172.18.0.7:7007 --cluster-slave --cluster-master-id 16a5ada35a648750daabdb91afa54ba6c62a26c4 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. >>> Adding node 172.18.0.9:7009 to cluster 172.18.0.7:7007 >>> Performing Cluster Check (using node 172.18.0.7:7007) S: a1dc21e356f983ce8f6af9ffd63e5819f6168f34 172.18.0.7:7007slots: (0 slots) slavereplicates 4a6116ea0bd3e13e603fc93a96e639b1b257e873 M: 4a6116ea0bd3e13e603fc93a96e639b1b257e873 172.18.0.3:7003slots:[5461-10922] (5462 slots) master1 additional replica(s) M: 9d257e1f3be993ab6cc418bee526ad8833e1b371 172.18.0.4:7004slots:[10923-16383] (5461 slots) master1 additional replica(s) M: 5ae566444b78ebc3d077c4fb7f17578b9725045f 172.18.0.2:7002slots:[0-5460] (5461 slots) master1 additional replica(s) M: 16a5ada35a648750daabdb91afa54ba6c62a26c4 172.18.0.8:7008slots: (0 slots) master S: 149b52decbb11b3fbf4199e97da5058bfae4af15 172.18.0.5:7005slots: (0 slots) slavereplicates 9d257e1f3be993ab6cc418bee526ad8833e1b371 S: aa7977e699159e0042a2cec003e4e163ed8c6af2 172.18.0.6:7006slots: (0 slots) slavereplicates 5ae566444b78ebc3d077c4fb7f17578b9725045f [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. >>> Send CLUSTER MEET to node 172.18.0.9:7009 to make it join the cluster. Waiting for the cluster to join>>> Configure node as replica of 172.18.0.8:7008. [OK] New node added correctly.

重新分配哈希槽

ip:port 為任意一個節點,

redis-cli --cluster reshard 172.18.0.7:7007 -a China

輸入需要遷移的槽點數

復制粘貼需要被接收的主節點

root@c9f5ce54a903:/data# redis-cli -c -a China --cluster reshard 172.18.0.4:7004 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. >>> Performing Cluster Check (using node 172.18.0.4:7004) M: 9d257e1f3be993ab6cc418bee526ad8833e1b371 172.18.0.4:7004slots:[10923-16383] (5461 slots) master1 additional replica(s) S: 28cfd99f6a93f49cbb8d9eff8ed6bc77d201d494 172.18.0.9:7009slots: (0 slots) slavereplicates 16a5ada35a648750daabdb91afa54ba6c62a26c4 M: 16a5ada35a648750daabdb91afa54ba6c62a26c4 172.18.0.8:7008slots: (0 slots) master1 additional replica(s) M: 4a6116ea0bd3e13e603fc93a96e639b1b257e873 172.18.0.3:7003slots:[5461-10922] (5462 slots) master1 additional replica(s) S: aa7977e699159e0042a2cec003e4e163ed8c6af2 172.18.0.6:7006slots: (0 slots) slavereplicates 5ae566444b78ebc3d077c4fb7f17578b9725045f S: a1dc21e356f983ce8f6af9ffd63e5819f6168f34 172.18.0.7:7007slots: (0 slots) slavereplicates 4a6116ea0bd3e13e603fc93a96e639b1b257e873 M: 5ae566444b78ebc3d077c4fb7f17578b9725045f 172.18.0.2:7002slots:[0-5460] (5461 slots) master1 additional replica(s) S: 149b52decbb11b3fbf4199e97da5058bfae4af15 172.18.0.5:7005slots: (0 slots) slavereplicates 9d257e1f3be993ab6cc418bee526ad8833e1b371 [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. How many slots do you want to move (from 1 to 16384)? 1000 What is the receiving node ID? 16a5ada35a648750daabdb91afa54ba6c62a26c4 Please enter all the source node IDs.Type 'all' to use all the nodes as source nodes for the hash slots.Type 'done' once you entered all the source nodes IDs. Source node #1: allReady to move 1000 slots.Source nodes:M: 9d257e1f3be993ab6cc418bee526ad8833e1b371 172.18.0.4:7004slots:[10923-16383] (5461 slots) master1 additional replica(s)M: 4a6116ea0bd3e13e603fc93a96e639b1b257e873 172.18.0.3:7003slots:[5461-10922] (5462 slots) master1 additional replica(s)M: 5ae566444b78ebc3d077c4fb7f17578b9725045f 172.18.0.2:7002slots:[0-5460] (5461 slots) master1 additional replica(s)Destination node:M: 16a5ada35a648750daabdb91afa54ba6c62a26c4 172.18.0.8:7008slots: (0 slots) master1 additional replica(s)Resharding plan:

測試set get 是否正常

Dokcer-redis集群刪除節點

# 說明:指定集群中任意節點IP、端口 和node_id 來刪除一個節點,從節點可以直接刪除,主節點不能直接刪除,刪除之后,該節點會被shutdown。 # f6a6957421b80409106cb36be3c7ba41f3b603ff 是Node-ID redis-cli -a China --cluster del-node ip:port f6a6957421b80409106cb36be3c7ba41f3b603ff

Redis持久化

根據業務情況配置持久化文件,

RDB介紹

? RDB是Redis用來進行持久化的一種方式,是把當前內存中的數據集快照寫入磁盤,也就是 Snapshot 快照(數據庫中所有鍵值對數據)。恢復時是將快照文件直接讀到內存里。

數據恢復

? 將備份文件 (dump.rdb) 移動到 redis 安裝目錄并啟動服務即可,redis就會自動加載文件數據至內存了。Redis 服務器在載入 RDB 文件期間,會一直處于阻塞狀態,直到載入工作完成為止。

獲取 redis 的安裝目錄可以使用 config get dir 命令

停止RDB持久化

? 有些情況下,我們只想利用Redis的緩存功能,并不像使用 Redis 的持久化功能(保存到硬盤),那么這時候我們最好停掉 RDB 持久化??梢酝ㄟ^上面講的在配置文件 redis.conf 中,可以注釋掉所有的 save 行來停用保存功能或者直接一個空字符串來實現停用:save “”

也可以通過命令:

redis-cli config set save ``" "

RDB優勢和劣勢

優勢

1.RDB是一個非常緊湊(compact)的文件,它保存了redis 在某個時間點上的數據集。這種文件非常適合用于進行備份和災難恢復。

2.生成RDB文件的時候,redis主進程會fork()一個子進程來處理所有保存工作,主進程不需要進行任何磁盤IO操作。

3.RDB 在恢復大數據集時的速度比 AOF 的恢復速度要快。

劣勢

1、RDB方式數據沒辦法做到實時持久化/秒級持久化。因為bgsave每次運行都要執行fork操作創建子進程,屬于重量級操作,如果不采用壓縮算法(內存中的數據被克隆了一份,大致2倍的膨脹性需要考慮),頻繁執行成本過高(影響性能)

2、RDB文件使用特定二進制格式保存,Redis版本演進過程中有多個格式的RDB版本,存在老版本Redis服務無法兼容新版RDB格式的問題(版本不兼容)

3、在一定間隔時間做一次備份,所以如果redis意外down掉的話,就會丟失最后一次快照后的所有修改(數據有丟失)

AOF介紹

? Redis的持久化方式之一RDB是通過保存數據庫中的鍵值對來記錄數據庫的狀態。而另一種持久化方式 AOF 則是通過保存Redis服務器所執行的寫命令來記錄數據庫狀態。

? RDB 持久化方式就是將 str1,str2,str3 這三個鍵值對保存到 RDB文件中,而 AOF 持久化則是將執行的 set,sadd,lpush 三個命令保存到 AOF 文件中。

? ①、appendonly:默認值為no,也就是說redis 默認使用的是rdb方式持久化,如果想要開啟 AOF 持久化方式,需要將 appendonly 修改為 yes。

②、appendfilename :aof文件名,默認是"appendonly.aof"

③、**appendfsync:**aof持久化策略的配置;

no表示不執行fsync,由操作系統保證數據同步到磁盤,速度最快,但是不太安全;

always表示每次寫入都執行fsync,以保證數據同步到磁盤,效率很低;

everysec表示每秒執行一次fsync,可能會導致丟失這1s數據。通常選擇 everysec ,兼顧安全性和效率。

? ④、no-appendfsync-on-rewrite:在aof重寫或者寫入rdb文件的時候,會執行大量IO,此時對于everysec和always的aof模式來說,執行fsync會造成阻塞過長時間,no-appendfsync-on-rewrite字段設置為默認設置為no。如果對延遲要求很高的應用,這個字段可以設置為yes,否則還是設置為no,這樣對持久化特性來說這是更安全的選擇。 設置為yes表示rewrite期間對新寫操作不fsync,暫時存在內存中,等rewrite完成后再寫入,建議yes。Linux的默認fsync策略是30秒??赡軄G失30秒數據。默認值為no。

⑤、auto-aof-rewrite-percentage:默認值為100。aof自動重寫配置,當目前aof文件大小超過上一次重寫的aof文件大小的百分之多少進行重寫,即當aof文件增長到一定大小的時候,Redis能夠調用bgrewriteaof對日志文件進行重寫。當前AOF文件大小是上次日志重寫得到AOF文件大小的二倍(設置為100)時,自動啟動新的日志重寫過程。

⑥、auto-aof-rewrite-min-size:64mb。設置允許重寫的最小aof文件大小,避免了達到約定百分比但尺寸仍然很小的情況還要重寫。

⑦、aof-load-truncated:aof文件可能在尾部是不完整的,當redis啟動的時候,aof文件的數據被載入內存。重啟可能發生在redis所在的主機操作系統宕機后,尤其在ext4文件系統沒有加上data=ordered選項,出現這種現象 redis宕機或者異常終止不會造成尾部不完整現象,可以選擇讓redis退出,或者導入盡可能多的數據。如果選擇的是yes,當截斷的aof文件被導入的時候,會自動發布一個log給客戶端然后load。如果是no,用戶必須手動redis-check-aof修復AOF文件才可以。默認值為 yes。

AOF數據恢復

? 重啟 Redis 之后就會進行 AOF 文件的載入。

異常修復命令:redis-check-aof --fix 進行修復

AOF重寫

? 由于AOF持久化是Redis不斷將寫命令記錄到 AOF 文件中,隨著Redis不斷的進行,AOF 的文件會越來越大,文件越大,占用服務器內存越大以及 AOF 恢復要求時間越長。為了解決這個問題,Redis新增了重寫機制,當AOF文件的大小超過所設定的閾值時,Redis就會啟動AOF文件的內容壓縮,只保留可以恢復數據的最小指令集??梢允褂妹?bgrewriteaof 來重新。

? 如果不進行 AOF 文件重寫,那么 AOF 文件將保存四條 SADD 命令,如果使用AOF 重寫,那么AOF 文件中將只會保留下面一條命令:

sadd animals ``"dog"` `"tiger"` `"panda"` `"lion"` `"cat"

也就是說 AOF 文件重寫并不是對原文件進行重新整理,而是直接讀取服務器現有的鍵值對,然后用一條命令去代替之前記錄這個鍵值對的多條命令,生成一個新的文件后去替換原來的 AOF 文件。

AOF 文件重寫觸發機制:通過 redis.conf 配置文件中的 auto-aof-rewrite-percentage:默認值為100,以及auto-aof-rewrite-min-size:64mb 配置,也就是說默認Redis會記錄上次重寫時的AOF大小,默認配置是當AOF文件大小是上次rewrite后大小的一倍且文件大于64M時觸發。

這里再提一下,我們知道 Redis 是單線程工作,如果 重寫 AOF 需要比較長的時間,那么在重寫 AOF 期間,Redis將長時間無法處理其他的命令,這顯然是不能忍受的。Redis為了克服這個問題,解決辦法是將 AOF 重寫程序放到子程序中進行,這樣有兩個好處:

①、子進程進行 AOF 重寫期間,服務器進程(父進程)可以繼續處理其他命令。

②、子進程帶有父進程的數據副本,使用子進程而不是線程,可以在避免使用鎖的情況下,保證數據的安全性。

使用子進程解決了上面的問題,但是新問題也產生了:因為子進程在進行 AOF 重寫期間,服務器進程依然在處理其它命令,這新的命令有可能也對數據庫進行了修改操作,使得當前數據庫狀態和重寫后的 AOF 文件狀態不一致。

為了解決這個數據狀態不一致的問題,Redis 服務器設置了一個 AOF 重寫緩沖區,這個緩沖區是在創建子進程后開始使用,當Redis服務器執行一個寫命令之后,就會將這個寫命令也發送到 AOF 重寫緩沖區。當子進程完成 AOF 重寫之后,就會給父進程發送一個信號,父進程接收此信號后,就會調用函數將 AOF 重寫緩沖區的內容都寫到新的 AOF 文件中。

這樣將 AOF 重寫對服務器造成的影響降到了最低。

AOF優缺點

優點:

①、AOF 持久化的方法提供了多種的同步頻率,即使使用默認的同步頻率每秒同步一次,Redis 最多也就丟失 1 秒的數據而已。

②、AOF 文件使用 Redis 命令追加的形式來構造,因此,即使 Redis 只能向 AOF 文件寫入命令的片斷,使用 redis-check-aof 工具也很容易修正 AOF 文件。

③、AOF 文件的格式可讀性較強,這也為使用者提供了更靈活的處理方式。例如,如果我們不小心錯用了 FLUSHALL 命令,在重寫還沒進行時,我們可以手工將最后的 FLUSHALL 命令去掉,然后再使用 AOF 來恢復數據。

缺點:

①、對于具有相同數據的的 Redis,AOF 文件通常會比 RDB 文件體積更大。

②、雖然 AOF 提供了多種同步的頻率,默認情況下,每秒同步一次的頻率也具有較高的性能。但在 Redis 的負載較高時,RDB 比 AOF 具好更好的性能保證。

③、RDB 使用快照的形式來持久化整個 Redis 數據,而 AOF 只是將每次執行的命令追加到 AOF 文件中,因此從理論上說,RDB 比 AOF 方式更健壯。官方文檔也指出,AOF 的確也存在一些 BUG,這些 BUG 在 RDB 沒有存在。

那么對于 AOF 和 RDB 兩種持久化方式,我們應該如何選擇呢?

如果可以忍受一小段時間內數據的丟失,毫無疑問使用 RDB 是最好的,定時生成 RDB 快照(snapshot)非常便于進行數據庫備份, 并且 RDB 恢復數據集的速度也要比 AOF 恢復的速度要快,而且使用 RDB 還可以避免 AOF 一些隱藏的 bug;否則就使用 AOF 重寫。但是一般情況下建議不要單獨使用某一種持久化機制,而是應該兩種一起用,在這種情況下,當redis重啟的時候會優先載入AOF文件來恢復原始的數據,因為在通常情況下AOF文件保存的數據集要比RDB文件保存的數據集要完整。Redis后期官方可能都有將兩種持久化方式整合為一種持久化模型。

RDB-AOF混合持久化

混合持久化是Redis 4.X之后的一個新特性,說是新特性其實更像是一種RDB&AOF的結合,持久化文件變成了RDB + AOF,首先由RDB定期完成內存快照的備份,然后再由AOF完成兩次RDB之間的數據備份。這樣就充分了利用了RDB 加載快,備份文件小等特點,也利用了AOF能盡可能不丟數據這個特性(進一步保證了數據一致性),當然了基本上丟失了AOF的可讀性。加載過程就是按部分進行加載的,先按照RDB進行加載,然后把AOF命令追加寫入就好了。在大多數場景下RDB + AOF的混合持久化模式其實還是很合適的.

這里補充一個知識點,在Redis4.0之后,之前有介紹的RDB和AOF兩種持久化方式,又新增了RDB-AOF混合持久化方式。

這種方式結合了RDB和AOF的優點,既能快速加載又能避免丟失過多的數據。

具體配置為:

#1,關閉RDB,參考上面的配置 #2,開啟AOF,參考上面的配置 aof-use-rdb-preamble yes

設置為yes表示開啟,設置為no表示禁用。

當開啟混合持久化時,主進程先fork出子進程將現有內存副本全量以RDB方式寫入aof文件中,然后將緩沖區中的增量命令以AOF方式寫入aof文件中,寫入完成后通知主進程更新相關信息,并將新的含有 RDB和AOF兩種格式的aof文件替換舊的aof文件。

混合持久化優缺點

優點

混合持久化結合了RDB持久化 和 AOF 持久化的優點, 由于絕大部分都是RDB格式,加載速度快,同時結合AOF,增量的數據以AOF方式保存了,數據更少的丟失。簡單來說:混合持久化方式產生的文件一部分是RDB格式,一部分是AOF格式。

缺點

兼容性差,一旦開啟了混合持久化,在4.0之前版本都不識別該aof文件,同時由于前部分是RDB格式,閱讀性較差

RDB和AOF,應該用哪一個?

如果你可以承受數分鐘以內的數據丟失, 那么你可以只使用 RDB 持久化。

有很多用戶都只使用 AOF 持久化, 但我們并不推薦這種方式: 因為定時生成 RDB 快照(snapshot)非常便于進行數據庫備份, 并且 RDB 恢復數據集的速度也要比 AOF 恢復的速度要快。如果只用AOF持久化,數據量很大時,在redis啟動的時候需要花費大量的時間。

如果你非常關心你的數據,建議使用 redis 4.0 以后的混合持久化特性。

循環插入數據測試腳本參考

for a in $(seq 1 10000);do redis-cli -p 7008 -a China set a$a $a;done

問題記錄

集群中執行get/set報錯

(error) MOVED 5798 172.0.0.X:XXXX

解決方案

Redis-cli啟動/訪問/請求時候增加-c 參數啟動集群模式

高可用測試報錯

進行高可用測試的時候,關閉任意一個主節點,在集群中執行get set命令報錯(error) CLUSTERDOWN The cluster is down 并且從節點沒有被選舉成主節點。

解決方案

配置文件中新增參數

##如果要最大的可用性,值設置為0。定義slave和master失聯時長的倍數,如果值為0,則只要失聯slave總是嘗試failover,而不管與master失聯多久。-----如果不加該參數,集群中的節點宕機后不會進行高可用恢復!!!!! cluster-slave-validity-factor 0 該參數在5.0之后為 cluster-replica-validity-factor 0

新增節點失敗

查看cluster nodes時候發現報錯 handshake - 0 0 0 disconnected

解決方案

因新增節點映射端口和總線端口與集群中的端口沖突,需要修改端口號

##節點映射端口 cluster-announce-port 6379 ##節點總線端口 cluster-announce-bus-port 16379

內存以及策略配置

如需要自定義配置

解決方案

#最大內存,注釋或設置0表示為物理機器最大可用內存,具體配置示情況而定* maxmemory 2g # 本文中采用默認配置 #內存淘汰策略,Redis使用內存超過最大內存時的處理機制(是否清除部分內存),默認是noeviction,不會清除內存,超過時會報錯 maxmemory-policy volatile-lru

局域網下其他主機無法使用集群

配置情況

主機A 與主機B 在同一個局域網下

容器redis集群在主機A 172.18.0.1/24 網段中

問題現象

該部署方式可以讓局域網中其他主機連接docker-redis集群中的單節點成功

能正常連接是因為 主機B 通過 主機A 在啟動容器的時候創建的防火墻規則。

DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:7002 to:172.18.0.2:7002

也就是通過局域網其他 主機B 嘗試執行redis-cli -c ip:port -a auth可以正常連接

實際上該 主機B 與 主機A 的容器172.18.0.1/24網絡環境是隔離的,所以get / set 跳躍到其他節點的時候 ,報錯連接超時。

redis-cli -c -h 192.168.2.200 -p 7002 -a China Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.192.168.2.200:7002> get a -> Redirected to slot [15495] located at 172.18.0.4:7004 Could not connect to Redis at 172.18.0.4:7004: Connection timed out Could not connect to Redis at 172.18.0.4:7004: Connection timed out (254.52s) not connected>

解決方案

理論上打通主機B到主機A上的容器172.18.0.1/24網絡即可。但不知道是否會影響效率

目前還沒有落地的解決方案(2020年09月08日16:23:22)

總結

以上是生活随笔為你收集整理的Docker-redis集群+混合持久化的全部內容,希望文章能夠幫你解決所遇到的問題。

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