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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

redis复制、哨兵、集群详细介绍

發布時間:2023/12/20 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 redis复制、哨兵、集群详细介绍 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

1、redis性能瓶頸在哪里?

2、redis為什么需要高可用?

3、主從復制

3.1、主從復制原理

3.1.1、復制初始化

3.1.2、復制同步階段

3.1.3、增量復制

3.1.4、無硬盤復制

3.2、異步復制導致主從庫數據不一致怎么解決?

3.3、主從復制崩潰恢復

4、哨兵

5、集群

5.1、插槽

5.2、集群的主從復制模型

5.3、集群一致性

5.4、搭建集群

6、redis模板配置文件

7、安裝Ruby


1、redis性能瓶頸在哪里?

首先說說redis為什么這么快。主要有以下幾點原因:

  • 純內存操作;
  • 單線程操作,避免頻繁上下文切換;
  • 采用IO多路復用模型;
  • 純ANSI C語言編寫;

由于redis是純內存操作并且采用了IO多路復用模型,因此redis的性能瓶頸不應該是CPU,內存和網絡延遲更應該是redis的性能瓶頸。

?

2、redis為什么需要高可用?

需要高可用的原因主要為:

  • 單點故障:因此需要將數據生成多個副本分布在不同的機器上;
  • 內存容易成為瓶頸:因此需要對數據進行分片;

redis有三種高可用方案,分別是:

  • 主從復制
  • 哨兵
  • 集群

?

3、主從復制

主庫:可以讀寫,將數據同步給從庫

從庫:只能讀,如果修改從庫數據會報錯(將slave-read-only設置為no就不會報錯)

一個主庫可以有多個從庫,但一個從庫只能有一個主庫。從庫也可以作為主庫。

主從復制可以同來實現讀寫分離,比如在電商系統中,讀的壓力大于寫,那么可以配置一主多從的redis高可用架構,主庫用來寫,多個從庫用來讀。

由于主從復制不能有多個主庫,因此當寫壓力過大時一主多從不再滿足需求,此時需要使用redis集群。

?

如何配置主從復制?兩種方法如下:

  • 在從庫的redis.conf中配置slaveof host port;
  • 在從庫執行slaveof host port命令;

?

info section命令以一種易于理解和閱讀的格式,返回關于Redis服務器的各種信息和統計數值。比如查看復制相關信息,可以使用info replication。

在一個主庫上執行info replication命令打印出來的信息如下所示。

127.0.0.1:6379> INFO replication # Replication role:master connected_slaves:1 slave0:ip=127.0.0.1,port=6380,state=online,offset=14,lag=0 master_replid:0dca9fd8627630d1058cd3ae740c39edc03f07c5 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:14 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:14

也可以使用role命令查看節點角色。

?

如果當前庫已經是某個主庫的從庫,那么執行slaveofhost port 將使當前庫停止對舊主庫的同步,丟棄舊數據集,轉而開始接收新主庫的同步。

另外,對一個從庫執行命令slave no one將使得這個從庫關閉復制功能,并從從庫轉變回主庫,原來同步所得的數據集不會被丟棄。

利用slave no one不會丟棄同步所得數據集這個特性,可以在主庫失敗的時候,將從庫作為新的主庫,從而實現無間斷運行。

?

3.1、主從復制原理

3.1.1、復制初始化

從庫啟動后,向主庫發生SYNC命令

主庫接收到命令并在后臺保存RDB快照(異步),并將保存快照期間接收到的客戶端命令緩存起來,然后一起發給從庫

從庫會將收到的內容寫入磁盤臨時文件,最后用臨時文件替換舊的RDB文件(在寫臨時文件期間,從庫不會阻塞客戶端請求,并且用同步前的數據響應客戶端,可以在redis.conf中配置slave-serve-stale-data為no來讓從庫在同步完成前對除了info和slave之外的所有命令響應錯誤)

?

3.1.2、復制同步階段

主庫每當收到寫命令就將命令同步給從庫(同步的內容就是redis通信協議的內容)

?

3.1.3、增量復制

主從庫斷開連接后,從庫再次連接主庫時,不必再進行一次復制初始化,而是直接增量復制(redis2.8版本開始支持)。

原理:

  • 在復制同步階段,主庫每接收到一個命令,都會將該命令放到積壓隊列中,并記錄好偏移量,從庫同步數據時,也會記錄好偏移量;
  • 增量復制使用psync命令代替sync命令,且psync命令會帶兩個參數,psync 主庫id 斷開前最新的命令偏移量;
  • 主庫收到psync命令后,會判斷從庫傳過來的主庫id與自身id是否相等;如果相等,則再判斷從庫傳過來的偏移量是否在積壓隊列中;
  • 如果上述兩個條件有一個不滿足,則不滿增量復制,而進行一次復制初始化;
  • ?

    3.1.4、無硬盤復制

    復制初始化時,由于主庫會進行快照生成RDB文件,因此會影響性能。redis2.8版本支持無硬盤復制(redis.conf中將repl-diskless-sync設置為yes),主庫直接通過網絡將數據發生給從庫

    ?

    3.2、異步復制導致主從庫數據不一致怎么解決?

    redis主從復制不保證強一致性,而是保證最終一致性。

    另外,可以在主庫的redis.conf中可以做如下配置。

    # 允許最小連接的從庫數 min-slaves-to-write 3 # 允許從庫最長失去連接的時間 min-slaves-max-lag 10

    以上兩個配置只要有一個不滿足,則主庫不可寫。

    ?

    3.3、主從復制崩潰恢復

    在主從復制中,主庫一般是禁用持久化的,因為從庫已經做數據備份了,禁用持久化可以提高性能。

    從庫崩潰,直接重啟從庫即可

    主庫崩潰,不能直接重啟主庫,因為主庫禁用持久化,如果重啟主庫則直接丟失數據,然后同步給從庫,從庫也相應地丟失數據。

    為了避免數據丟失,當主庫崩潰時,需要做以下兩步操作:

    在從庫執行slave no one命令將從庫升級為主庫

    重啟崩潰的主庫,然后使用slave命令將其設置為新主庫的從庫

    ?

    無論主庫崩潰還是從庫崩潰,都需要手動操作,手動操作不僅麻煩還容易出錯,因此redis提供哨兵這一機制來支持自動操作。

    ?

    4、哨兵

    哨兵的功能:

    • 監控主從庫是否正常運行;
    • 主庫故障時自動將主庫轉為從庫;

    可以部署多個哨兵,哨兵之間也會互相監控。

    哨兵甚至可以監控多個主從系統,通過在sentinel.conf中配置多行sentinel monitor配置來實現。

    哨兵是一個可執行文件,在redis的src目錄下面,名稱為redis-sentinel。

    在sentinel.conf中,做如下配置。

    sentinel monitor mymaster 127.0.0.1 6379 1

    mymaster是主庫名。

    127.0.0.1:6379是主庫的ip和端口號,sentinel.conf中只需要配置要監控的主庫即可,而從庫sentinel會根據主庫自動發現。

    1表示至少需要1個哨兵節點同意。

    然后執行以下命令啟動sentinel進程

    src/redis-sentinel? sentinel.conf

    ?

    下面演示一下哨兵是如何自動化監控主從復制的。

    為了簡單起見,現有一主一從,主庫為127.0.0.1::6379,從庫為127.0.0.1::6380。

  • 啟動一個哨兵進程,觀察啟動日志;
  • 然后我們刻意停掉主庫,觀察哨兵的日志變化;
  • 最后,手動重啟舊主庫,觀察哨兵的日志變化(哨兵只會幫助我們選舉新的主庫,然后將舊主庫變為新主庫的從庫,并不會為我們重啟舊主庫);
  • 以上三步哨兵的日志如下圖所示。

    ?

    5、集群

    雖然引入了哨兵,但主從復制中每個節點都存儲全量數據,因此最大能存儲多少數據受限于內存最小的那個節點,形成木桶效應,因此需要對redis做數據分片。

    客戶端分片:

    • 舊版redis使用使用客戶端分片,即由客戶端決定每個鍵交由那個數據庫節點存儲;
    • 弊端:如果集群增刪節點,則需要手動遷移數據,且為了保證遷移過程中的數據一致性需要將集群暫時下線;

    redis3.0開始支持集群。

    集群特點:

    • 擁有和單機實例同樣的性能;
    • 在網絡分區后提供一定的可訪問性以及對主庫故障恢復的支持;
    • redis集群并不支持處理多個key的命令(如mget),這是因為在不同的節點間移動數據會達不到像單機redis那樣的性能,在高負載的情況下可能會導致不可預料的錯誤;
    • 只能使用0號數據庫,如果用select切換則報錯;
    • 支持數據分片和主從復制;

    ?

    5.1、插槽

    redis cluster沒有使用一致性hash,而是有一個哈希槽的概念,默認有16384個插槽。

    redis將每個鍵鍵名的有效部分使用CRC16算法計算出散列值,然后對16384取余。

    有效部分:

    • 如果鍵名中包含{至少一個字符},則有效部分為大括號里面的內容,比如{user001}:username和{user001}:password這兩個鍵的有效部分都是user001,那么它們會被分配到一個結點上,可以使用涉及多鍵的命令(比如mget)去處理它們;
    • 如果鍵名中不包含{至少一個字符},則整個鍵名都是有效部分;
    • 如果有多個大括號則算法會在匹配第一個大括號就停止,然后進行判斷。比如鍵a{b}cozvdkddzhkzd的有效部分為b,而a{}cozvdkddzhkzd的有效部分為整個鍵名;

    集群中的每個主節點負責分配一部分插槽,cluster slots命令用于查看插槽分配情況,而從節點只負責備份主節點的插槽。

    增刪節點怎么辦?

    • 比如現在有A、B、C三個主節點,假如想增加D節點,那么只要將A、B、C節點中的部分槽遷移到D即可,如果想刪除B節點,則只需要將B節點的槽遷移到A、C節點即可。

    增刪節點或者是修改某個節點槽的數量都不會導致集群不可用。

    ?

    5.2、集群的主從復制模型

    redis集群是支持主從復制的,目的是為了提高可用性。

    比如當前集群有三個主節點A、B、C和三個從節點A1、B1、C1,則有以下情況:

  • 如果從節點B1掛掉了,則不影響,整個集群可用;
  • 如果主節點B掛掉了,集群會選舉B1為新的主節點,整個集群仍然是可用的,待B重啟后會變為B1的從節點;
  • 但如果B和B1都掛掉了,那集群就不可用了,比如執行set命令時,會報錯:(error) CLUSTERDOWN The cluster is down;
  • 主從節點只要不是都掛,則不需要開啟持久化,如果都掛,那必須要開啟持久化了。

    如果你的redis cluster只用于緩存,那么為了最大程度提升性能,不需要開啟持久化。

    如果你的redis cluster用來做數據庫,那么就要看情況了,如果主從同時掛掉的幾率不大且你對數據丟失的容忍度還行的話,就不需要開啟持久化,否則需要。

    ?

    5.3、集群一致性

    redis集群不保證強一致性,導致不一致的可能原因有兩個:

    • 主從節點間是異步復制的;
    • 某個主節點發生了網絡分區,比如集群有A、B、C三個主節點以及對應的從節點A1、B1、C1,此時主節點B與集群形成網絡分區,在網絡分區期間某個客戶端往B節點寫數據,如果網絡分區很短暫,那數據就不會丟失;但如果在網絡分區期間集群重新選舉了B1節點為主節點,那么數據就會丟失了;

    形成網絡分區的節點的超時時間是可以通過cluster-node-timeout這個配置項配置的,如果沒有超時,則客戶端可以正常向分區節點寫數據,如果超時則不能寫入。

    ?

    5.4、搭建集群

    集群至少需要3個節點才能正常運行,下面演示一下在單個centos系統上配置一個3主3從的redis集群。

    集群重要配置如下。

    cluster-enable yes cluster-node-timeout 5000 cluster-config-file nodes.conf

    集群文件夾結構如下圖所示。

    6381節點配置文件內容如下,其它節點類似(關于模板配置文件見本文第6節-redis模板配置文件)。

    include ../run/redis-cluster.conf port 6381 pidfile /usr/local/redis-cluster/run/redis-6381.pid logfile /usr/local/redis-cluster/run/redis-6381.log dir /usr/local/redis-cluster/6381/ cluster-config-file /usr/local/redis-cluster/run/nodes-6381.conf

    啟動各個節點,用redis-cli連接任意節點執行info cluster命令可以查看集群狀態,cluster_enable為1表示可用。

    但此時還不能寫數據,比如在任意節點執行set age 10命令時,會報錯:(error) CLUSTERDOWN Hash slot not served。

    這是因為此時每個節點還是獨立狀態,下面需要將各節點聯系在一起,即初始化集群。

    如果是舊版本的redis,可以使用src/redis-trib(ruby語言編寫,安裝Ruby見本文第7節-安裝Ruby)來初始化集群,初始化集群的命令如下。

    src/redis-trib.rb --replicas 1 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384 127.0.0.1:6385 127.0.0.1:6386

    replicas 1表示每個主節點的副本個數為1。

    如果執行上述命令提示WARNING: redis-trib.rb is not longer available!,則表示當前版本的redis已經不支持redis-trib.rb,具體的提示信息如下圖所示。

    根據該提示,我們知道了應該使用redis-cli來代替redis-trib.rb。

    首先在redis-cli中執行cluster help命令,查看與集群cluster相關的命令有哪些,如下所示。

    ADDSLOTS <slot> [slot ...] -- 為當前節點分配槽位 BUMPEPOCH -- Advance the cluster config epoch. COUNT-failure-reports <node-id> -- 根據<node-id>返回失敗報告的數量 COUNTKEYSINSLOT <slot> - 根據槽位返回key數量 DELSLOTS <slot> [slot ...] -- 在當前節點刪除指定槽位 FAILOVER [force|takeover] -- 將當前復制節點提升為主節點 FORGET <node-id> -- 從集群中移除節點 GETKEYSINSLOT <slot> <count> -- 返回當前節點存儲在插槽中的鍵名 FLUSHSLOTS -- 刪除當前節點的槽位信息 INFO - 返回關于集群的信息. KEYSLOT <key> -- 根據key返回hash槽 MEET <ip> <port> [bus-port] -- 將節點連接到工作集群 MYID -- 返回當前節點id NODES -- 返回節點看到的集群配置。輸出格式:<id> <ip:port> <flags> <master> <pings> <pongs> <epoch> <link> <slot> ... <slot> REPLICATE <node-id> -- 配置當前節點為<node-id>的復制節點 RESET [hard|soft] -- 重置當前節點 (默認: soft). SET-config-epoch <epoch> - Set config epoch of current node. SETSLOT <slot> (importing|migrating|stable|node <node-id>) -- 設置槽位狀態. REPLICAS <node-id> -- 返回指定主節點的副本節點 SLOTS -- 返回關于槽范圍映射的信息。每個系列都是由:start, end, master and replicas IP addresses, ports and ids

    ?

    初始化集群步驟:

    1、使用cluster meet命令將各個節點聯系在一起,如下圖所示。

    再執行cluster nodes命令,可以看到六個節點聯系在一起了,如下圖所示。但此時這六個節點都是主庫,并且還沒有分配插槽。

    2、使用cluster addslots命令為所有主庫分配插槽。

    由于cluster addslots命令不支持批量添加插槽,所以我寫了一個shell腳本利用for循環批量分配插槽,shell腳本如下。

    for ((i=$3; i<=$4; i ++)) do6381/src/redis-cli -h $1 -p $2 cluster addslots $i > /dev/null done

    現在讓6381、6382、6383為主庫,我們將16384個插槽分配給這三個主庫,具體分配情況如下:

    6381占0~5460號插槽,共5461個

    6382占5461~10920號插槽,共5462個

    6383占10921~16383號插槽,共5461個

    執行如下命令即可分配插槽:

    ./cluster-addslots.sh 127.0.0.1 6381 0 5460 ./cluster-addslots.sh 127.0.0.1 6382 5461 10920 ./cluster-addslots.sh 127.0.0.1 6383 10921 16383

    最新使用cluster slots命令查找插槽分配情況。

    ?

    3、使用cluster replicate命令設置從庫

    執行如下命令,使得:

    • 6384為6381的從庫;
    • 6383為6382的從庫;
    • 6384為6383的從庫;
    6381/src/redis-cli -h 127.0.0.1 -p 6384 cluster replicate 6381的節點id 6381/src/redis-cli -h 127.0.0.1 -p 6385 cluster replicate 6382的節點id 6381/src/redis-cli -h 127.0.0.1 -p 6386 cluster replicate 6383的節點id

    最后使用cluster nodes命令查看集群節點信息,即可看到有三個主庫和三個從庫,如下圖所示。

    ?

    集群搭建好后,我們使用redis-cli往集群寫一些數據試試,但如果不幸運的話寫第一個數據就會報錯,如下圖所示。

    這是因為redis-cli連接的是6381這個節點,但user:1這個key會被分配到6382節點,因此寫入錯誤。

    解決辦法是,redis-cli支持以集群模式連接到某一個節點,并且支持自動重定向,如下圖所示。

    ?

    6、redis模板配置文件

    redis-5.0.5版本默認配置文件(去除注釋)如下。

    ################################## INCLUDES ################################### ################################## MODULES ##################################### ################################## NETWORK ##################################### bind 127.0.0.1 protected-mode yes port 6379 tcp-backlog 511 timeout 0 tcp-keepalive 300 ################################# GENERAL ##################################### daemonize no supervised no pidfile /var/run/redis_6379.pid loglevel notice logfile "" databases 16 always-show-logo yes ################################ SNAPSHOTTING ################################ save 900 1 save 300 10 save 60 10000 stop-writes-on-bgsave-error yes rdbcompression yes rdbchecksum yes dbfilename dump.rdb dir ./ ################################# REPLICATION ################################# replica-serve-stale-data yes replica-read-only yes repl-diskless-sync no repl-diskless-sync-delay 5 repl-disable-tcp-nodelay no replica-priority 100 ################################## SECURITY ################################### ################################### CLIENTS #################################### ############################## MEMORY MANAGEMENT ################################ ############################# LAZY FREEING #################################### lazyfree-lazy-eviction no lazyfree-lazy-expire no lazyfree-lazy-server-del no replica-lazy-flush no ############################## APPEND ONLY MODE ############################### appendonly no appendfilename "appendonly.aof" appendfsync everysec no-appendfsync-on-rewrite no auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb aof-load-truncated yes aof-use-rdb-preamble yes ################################ LUA SCRIPTING ############################### lua-time-limit 5000 ################################ REDIS CLUSTER ############################### ########################## CLUSTER DOCKER/NAT support ######################## ################################## SLOW LOG ################################### slowlog-log-slower-than 10000 slowlog-max-len 128 ################################ LATENCY MONITOR ############################## latency-monitor-threshold 0 ############################# EVENT NOTIFICATION ############################## notify-keyspace-events "" ############################### ADVANCED CONFIG ############################### hash-max-ziplist-entries 512 hash-max-ziplist-value 64 list-max-ziplist-size -2 list-compress-depth 0 set-max-intset-entries 512 zset-max-ziplist-entries 128 zset-max-ziplist-value 64 hll-sparse-max-bytes 3000 stream-node-max-bytes 4096 stream-node-max-entries 100 activerehashing yes client-output-buffer-limit normal 0 0 0 client-output-buffer-limit replica 256mb 64mb 60 client-output-buffer-limit pubsub 32mb 8mb 60 hz 10 dynamic-hz yes aof-rewrite-incremental-fsync yes rdb-save-incremental-fsync yes ########################### ACTIVE DEFRAGMENTATION #######################

    將默認的配置文件做如下修改(如何修改具體看需求),使其變為所有節點通用的模板配置文件:

    • 注釋bind
    • protected-mode改為no
    • 注釋port
    • daemonize改為yes
    • 注釋pidfile
    • 注釋logfile
    • 注釋三個save
    • 注釋dir

    如果是集群模式,則還需要:

    • 新增cluster-enabled yes;

    然后再針對單個節點用include指令導入公共模板(注意使用相對路徑,否則啟動會報錯),然后再做一些本節點的特殊配置,如下所示:

    include?../run/redis_useful.conf port 6379 pidfile /var/run/redis_6379.pid logfile /var/log/redis_6379.log dir /usr/local/redis-5.0.5/

    ?

    7、安裝Ruby

  • wget https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.1.tar.gz
  • tar -xvzf ruby-3.0.1.tar.gz?
  • ./configure
  • make
  • make install
  • 總結

    以上是生活随笔為你收集整理的redis复制、哨兵、集群详细介绍的全部內容,希望文章能夠幫你解決所遇到的問題。

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