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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

Redis 实战之主从复制、高可用、分布式

發(fā)布時間:2023/12/4 数据库 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Redis 实战之主从复制、高可用、分布式 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

簡介

本節(jié)內容基于 CentOS 7.4.1708,Redis 3.2.12 環(huán)境實驗。

Redis 是一個開源的高性能鍵值對數(shù)據(jù)庫。

安裝:yum install -y redis

特性:

  • 高性能 Key-Value 服務器

  • 多種數(shù)據(jù)結構

  • 豐富功能

    • 緩存(get|set)

    • 計數(shù)器(incre)

    • 消息隊列(publish|subcrib)

  • 高可用(v2.8 redis-sentinel)

  • 分布式(v3.0 redis-cluster)

可執(zhí)行文件:

  • redis-server:服務端

  • redis-cli:客戶端

  • redis-benchmark:性能測試工具

  • redis-check-aof:aof修復工具

  • redis-check-dump:rdb修復工具

  • redis-sentinel:sentinel服務端

啟動方式:

  • 最簡啟動:默認配置直接啟動redis-server

  • 動態(tài)參數(shù)啟動:命令行指定配置啟動redis-server

  • 配置文件啟動(推薦):指定配置文件啟動redis-server

啟動驗證:

  • ps -ef|grep redis

  • redis-cli -h locahost -p 6379 ping

由于 redis 是單線程的,推薦在一臺多核CPU機器上部署多個 redis 實例充分發(fā)揮。

持久化

redis 持久化支持2種:

  • RDB:快照方式,相當于 MySQL 中的 dump

  • AOF:寫日志方式,相當于 MySQL 中的 binlog,推薦使用

  • 注意:

  • 當同時開啟 RDB 和 AOF 的時候,redis啟動的時候會讀取 AOF 還原數(shù)據(jù)。

  • 推薦:關閉 RDB 持久化機制,開啟 AOF

  • RDB

    RDB是什么:

  • RDB方式的持久化是通過快照(snapshortting)完成的,當符合一定條件時Redis會自動將內存中所有數(shù)據(jù)完整的壓縮存儲到硬盤上。

  • RDB開啟條件由2個參數(shù) 時間 和 改動次數(shù)構成。如:save 900 1

  • RDB文件由2個參數(shù) dir 和 dbfilename 分別指定目錄 和 文件名

  • RDB方式是Redis默認的持久化方式。

  • 觸發(fā)命令:

  • save 命令(阻塞)

  • bgsave 命令(fork過程阻塞)

  • 主要觸發(fā)方式:

  • 自動觸發(fā)規(guī)則(內部調用bgsave,不推薦開啟)

  • 全量復制(內部調用bgsave)

  • 過程:

  • 執(zhí)行 save 或 bgsave 命令

  • 生成新的 rdb 文件,如:temp-36985.rdb

  • 覆蓋 rdb 文件,如:dump-6379.rdb

  • 優(yōu)點:

  • 啟動速度快

  • 占用空間小

  • 缺點:

  • 容易丟失數(shù)據(jù)

  • 時間復雜度O(n)

  • 關閉RDB方式:

    redis-cli config set save ""

    注意:

    RDB并不能真正的關閉,在主從復制時主從都會生成RDB文件

    AOF

    AOF是什么:

  • AOF是純文本文件,會記錄 Redis 的每次改動命令(不記錄查詢)。

  • AOF開啟條件:appendonly yes

  • AOF文件由2個參數(shù) dir 和 appendfilename 分別指定目錄 和 文件名

  • AOF方式 默認情況下Redis并沒有開啟。

  • 由于每次改動都會記錄,產(chǎn)生2個問題:

  • 每次改動都寫入硬盤,普通硬盤只能承受幾百次qps。通過寫入策略來調整

  • 對同1個key執(zhí)行幾次操作就記錄幾次,冗余量特別大。通過 aof 文件重寫來調整

  • AOF文件有3種寫入策略:

  • always(每次寫入都會fsync同步到硬盤)

  • everysec(默認,1s寫1次)

  • no(并非不寫,交給系統(tǒng)控制預計30s寫1次)

  • AOF重寫:

  • 重寫方式

  • 手動執(zhí)行 bgrewriteaof 命令

  • 自動觸發(fā)規(guī)則(通過指定最小aof文件和aof增長率來自動內部調用 bgrewriteaof)

  • 過程

  • fork 出子進程

  • 子進程執(zhí)行 bgrewriteaof 命令

  • 父進程將新接收的命令,同時寫到 aof 文件和 aof_rewrite_buffer文件中。(在 aof 重寫時,可配置關閉aof寫入)

  • 子進程將 aof_rewrite_buffer 文件追加到新 aof 文件中。

  • 覆蓋舊的 aof 文件

  • 注意:

  • 采用 everysec 方式,最多可能丟失 2s 的數(shù)據(jù)。

  • 主從復制

    為什么需要主從復制:

    通過持久化保證 Redis 在服務器重啟的情況下數(shù)據(jù)也不會丟失。但數(shù)據(jù)在一臺服務器上,如果服務器的硬盤壞了,也會導致數(shù)據(jù)丟失。為了避免單點故障,Redis 提供了主從復制高可用方案。

    主從復制結構:

  • 1個 master 可以有多個 slave

  • 1個 slave 只能有1個 master

  • 數(shù)據(jù)流向單向 master -> slave

  • 開啟復制:

  • 命令:--slaveof ip port

  • 配置:slaveof ip port(默認配置都是master)

  • 關閉復制:

    slaveof no one

    復制類型:

  • 全量復制(首次 或者 網(wǎng)絡斷開時間比較長)

  • 部分復制(在網(wǎng)絡抖動一定范圍的情況下,v2.8以上可配置復制緩存區(qū)repl-backlog-size)

  • 全量復制過程:

  • slave 節(jié)點 發(fā)起 psync runid offset:psync ? -1

  • master 節(jié)點 返回 fullresync runid offset

  • master 節(jié)點 bgsave 保存當前數(shù)據(jù)到 rdb

  • master 節(jié)點 在此期間接收到新的數(shù)據(jù)存儲到 buffer 中

  • master 節(jié)點 send RDB、send buffer

  • slave 節(jié)點 flush old data

  • slave 節(jié)點 load RDB、load buffer

  • 在master重啟(master 的run_id更新)和slave重啟(slave 的run_id丟失)時都會發(fā)生全量復制,通過 info server 可以查看run_id。

    部分復制過程:

  • slave 節(jié)點 發(fā)起 psync runid offset

  • master 節(jié)點 確認 runid 和 offset沒問題后,發(fā)送增量數(shù)據(jù)

  • slave 節(jié)點 接收同步數(shù)據(jù)。

  • 當全量復制完成 或 網(wǎng)絡抖動一定范圍 時,master 相當于 slave 的 client 進行增量更新數(shù)據(jù)。

    Redis Sentinel

    Redis-Sentinel是什么?

  • Redis-Sentinel是Redis官方推薦的高可用性(HA)解決方案

  • Redis-Sentinel本身也是一個獨立運行的進程,它能監(jiān)控多個 master-slave 集群,發(fā)現(xiàn) master宕機 后能進行自動故障轉移。

  • sentinel工作原理:

  • 準備多個Redis Sentinel節(jié)點(建議至少3個節(jié)點,避免單點故障)

  • 多個 Sentinel 節(jié)點發(fā)現(xiàn)并確認 master 主觀下線

  • 超過 quorum 個 sentinel 判定確認 客觀下線

  • 選出 1個 sentinel 節(jié)點作為領導

  • 選出 1個 slave 節(jié)點作為 master

  • 切換 slave 節(jié)點的 master 為新的 master

  • 通知 client 主從變化

  • 等待故障的 master 復活成為新的 slave

  • Client 不直接連接 Redis 節(jié)點,應該連接 Sentinel 節(jié)點獲取 Redis Info

  • 2種下線判定:

  • sdown(subjectively down,主觀下線):每個 sentinel 判定 redis 節(jié)點下線。

  • odown(objectively down,客觀下線):超過 quorum 個 sentinel 判定 redis 節(jié)點下線。

  • 啟動方式:

  • redis-sentinel /path/to/sentinel.conf

  • redis-server /path/to/sentinel.conf --sentinel

  • 三個定時任務:

  • 每個 Sentinel 節(jié)點每秒通過 redis 的?__sentinel__:hello?發(fā)布一條消息,宣布自己的存在。同時也訂閱來確定其他的 Sentinel 節(jié)點。

  • 每個 Sentinel 節(jié)點每秒對其他 redis 節(jié)點執(zhí)行 ping。確定是否下線。

  • 每個 Sentinel 節(jié)點每10秒 對 master 和 slave 執(zhí)行 info,確定 slaves。

  • 配置模擬:

  • 配置 Redis 開啟主從復制

  • 配置 Sentinel 監(jiān)控主節(jié)點

  • echo "停止當前所有redis-server + redis-sentinel"; ps -x | grep redis | grep -v grep | awk '{print $1}' | xargs -r killecho "生成并啟動3個 redis 配置";for port in 6379 6380 6381 ;doecho -e "daemonize yes\nport $port\npidfile /var/run/redis-$port.pid\nlogfile /var/log/redis/redis-$port.log\n" > /etc/redis/redis-$port.confif [ $port != 6379 ];thenecho "slaveof 127.0.0.1 6379" >> /etc/redis/redis-$port.conffiredis-server /etc/redis/redis-$port.confdoneecho "生成并啟動3個 redis-sentinel 配置";for port in 26379 26380 26381 ;doecho -e "daemonize yes\nport $port\ndir /tmp\nsentinel monitor mymaster 127.0.0.1 6379 2\nsentinel down-after-milliseconds mymaster 3000\nsentinel parallel-syncs mymaster 1\nsentinel failover-timeout mymaster 60000\nlogfile /var/log/redis/sentinel-$port.log\n" > /etc/redis/redis-sentinel-$port.conf redis-sentinel /etc/redis/redis-sentinel-$port.confdoneecho "結束";

    常用的channel:

    • +switch-master:切換主節(jié)點

    • +convert-to-slave:切換從節(jié)點

    • +sdown:主觀下線

    .NET Core環(huán)境開發(fā):

    dotnet add package StackExchange.Redis

    var options = new ConfigurationOptions() {CommandMap = CommandMap.Sentinel,EndPoints = { { "192.168.0.51", 26379}, {"192.168.0.51", 26381}, {"192.168.0.51", 26380} },AllowAdmin = true,TieBreaker = "",ServiceName = "mymaster",SyncTimeout = 5000};var sentinelConn = ConnectionMultiplexer.Connect(options);var master = sentinelConn.GetServer("192.168.0.51",26381).SentinelGetMasterAddressByName("mymaster");// ...var conn = ConnectionMultiplexer.Connect(master); sentinelConn.GetSubscriber().Subscribe("+switch-master", (channel, message) => { ? ?// mymaster 192.168.0.51 6380 192.168.0.51 6381Console.WriteLine((string)message); ? ?// ...conn = ConnectionMultiplexer.Connect(ip);conn.GetDatabase().StringSet("hello","故障切換后值"); }); sentinelConn.GetSubscriber().Subscribe("+convert-to-slave", (channel, message) => { ? ?// slave 192.168.0.51:6379 192.168.0.51 6379 @ mymaster 192.168.0.51 6380Console.WriteLine((string)message); });conn.GetDatabase().StringSet("hello","原始值");

    注意:

  • 所有Sentinel和Redis不能在同一個節(jié)點

  • Redis Cluster

    實際上大部分場景下,Redis Sentinel已經(jīng)足夠好。請根據(jù)實際情況采用 Redis Cluster。

    Redis Cluster 采用虛擬槽分區(qū)方式(16384個虛擬槽)。

    原因:

    • 需要更高的qps(超過 10w/s)

    • 需要更高的數(shù)據(jù)量(超過 500G)

    • 需要更高的帶寬(超過 1000M)

    常用命令:

  • redis-cli -h localhost -p 6382 cluster info:查看集群基本信息

  • redis-cli -h localhost -p 6382 cluster slots:查看集群slot信息

  • redis-cli -h localhost -p 6382 cluster nodes:查看集群node信息

  • redis-cli -c:move自動跳轉執(zhí)行

  • yum install -y redis-trib:官方提供了基于 ruby 的工具方便部署

  • 搭建 Cluster 過程:

  • 配置
    cluster-enabled:yes
    cluster-node-timeout 15000
    cluster-require-full-coverage no
    cluster-config-file node-${port}.conf

  • meet
    redis-cli cluster meet ip port

  • 分配槽(0-16383)
    redis-cli cluster addslots {0....5461}

  • 分配主從(node-id)
    redis-cli cluster replicate {nodeid}

  • redis-cli 搭建:

    echo "停止當前所有redis-server + redis-sentinel"; mkdir /etc/redis ps -x | grep redis | grep -v grep | awk '{print $1}' | xargs -r killsleep 1echo "啟動6個 redis + meet";for port in 7000 7001 7002 7003 7004 7005;doecho -e "daemonize yes\nport $port\npidfile /var/run/redis-$port.pid\nlogfile /var/log/redis/redis-$port.log\ncluster-enabled yes\ncluster-config-file nodes-$port.conf\ncluster-require-full-coverage no" > /etc/redis/redis-$port.conf redis-server /etc/redis/redis-$port.confdonefor port in 7000 7001 7002 7003 7004 7005;doredis-cli -p $port FLUSHALLredis-cli -p $port cluster reset soft ? ?if [ $port != 7000 ];thenredis-cli -p 7000 cluster meet 127.0.0.1 $portfidonesleep 1echo "分配 16383 槽"; redis-cli -p 7000 cluster addslots {0..5461} redis-cli -p 7001 cluster addslots {5462..10922} redis-cli -p 7002 cluster addslots {10922..16383}echo "配置 replication"redis-cli -p 7003 cluster replicate `redis-cli -p 7000 cluster nodes | grep myself | awk '{print $1}'` redis-cli -p 7004 cluster replicate `redis-cli -p 7001 cluster nodes | grep myself | awk '{print $1}'` redis-cli -p 7005 cluster replicate `redis-cli -p 7002 cluster nodes | grep myself | awk '{print $1}'`

    redis-trib搭建:

  • 準備節(jié)點

  • 使用redis-trib搭建
    redis-trib create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005

  • redis-trib create 會自動meet、addslots、replicate。

    配置

    查看去除注釋的配置:cat /etc/redis.conf | grep -v '^#' | grep -v '^$'

    設置配置:config set key value

    查詢所有配置:config get *

    基礎配置

    配置項默認值推薦值說明
    daemonizenoyes(docker環(huán)境例外)是否以守護進程方式啟動
    port6379-redis服務監(jiān)聽端口
    pidfile/var/run/redis.pid/var/run/redis-{port}.pidpid文件
    logfile/var/log/redis/redis.log/var/log/redis/redis-{port}.log日志文件名:redis工作時產(chǎn)生的日志。
    dir/var/lib/redis-rdb文件和aof文件目錄。推薦使用大文件目錄。(不指定則為當前目錄)
    protected-modeyes-限制為127.0.0.1訪問。啟用條件:沒有bindIP 和 沒有設置密碼

    RDB配置

    配置項默認值推薦值說明
    dbfilenamedump.rdbdump-{port}.rdbrdb文件名
    rdbcompressionyesyes壓縮格式
    stop-writes-on-bgsave-erroryesyes出現(xiàn)錯誤時,停止新的寫入
    rdbchecksumyesyes數(shù)據(jù)完整性校驗

    AOF配置

    配置項默認值推薦值說明
    appendonlynoyes是否開啟 aof 模式
    appendfilename"appendonly.aof""appendonly-{port}.aof"aof文件名
    appendfsynceveryseceverysecfsync方式
    no-appendfsync-on-rewriteno(安全)yes(高性能)在 aof 重寫時,是否停止fsync
    auto-aof-rewrite-min-size64mb-aof文件重寫的最小大小
    auto-aof-rewrite-percentage100-aof文件增長率
    aof-load-truncatedyesyes當 aof 文件不完整的時候,將完整的部分加載

    主從復制配置

    配置項默認值推薦值說明
    slowlog-max-len1281000慢查詢隊列長度
    slowlog-log-slow-than100001000(qps1w)慢查詢閾值(單位:微秒)
    slaveofip port-主從復制配置
    slave-read-onlyyesyes從節(jié)點只讀
    repl-backlog-size104857610M復制緩存區(qū),可以再原有基礎上稍微增加

    Sentinel配置

    配置項默認值推薦值說明
    daemonizenoyes是否以守護進程方式啟動
    port26379{port}sentinel監(jiān)聽端口
    dir/tmp-工作目錄
    sentinel monitormymaster 127.0.0.1 6379 2-odown(objectively down,客觀下線)規(guī)則:masterName ip port quorum
    sentinel down-after-millisecondsmymaster 30000-sdown(subjectively down,主觀下線)規(guī)則:masterName timeout(單位:毫秒)
    sentinel parallel-syncsmymaster 1-并發(fā)同步數(shù)量
    sentinel failover-timeoutmymaster 180000-多長時間內不再故障轉移(單位:毫秒)
    logfile/var/log/redis/sentinel.log/var/log/redis/sentinel-{port}.log日志文件

    Cluster配置

    配置項默認值推薦值說明
    cluster-enablednoyes開啟cluster模式
    cluster-node-timeout15000-故障轉移時間,主觀下線超時時間
    cluster-config-filenodes-{port}.confcluster配置
    cluster-require-full-coverageyesnocluster 所有節(jié)點全部在線才提供服務

    常見問題

    redis是單線程嗎?為什么這么快?

    redis其實不是單線程(fsync,bgsave),一次只能執(zhí)行一條命令。

    慢查詢

    查詢慢查詢隊列:slowlog get

    客戶端請求的生命周期:

  • 發(fā)送命令

  • 排隊

  • 執(zhí)行命令

  • 返回結果

  • 慢查詢發(fā)送在第三個階段(執(zhí)行命令),客戶端超時不一定是慢查詢。

    fork

  • fork本身是同步操作

  • 內存越大耗時越長

  • info:latest_fork_usec

  • 規(guī)避全量復制

    • 首次全量復制:不可避免

    • runid 不匹配:故障轉移

    • 復制緩沖區(qū)不足:配置repl_backlog_size調整大

    常用命令

    • KEYS pattern :查詢keys

    • DBSIZE :查詢所有鍵的數(shù)量

    • EXISTS key :查詢指定key是否存在

    • TYPE key :查詢key的類型

    • DEL key :刪除指定key

    • INFO :查看server 信息如:INFO memory

    INFO 信息:

    • used_memory redis 當前使用的內存總量

    • used_memory_rss redis 當前使用的內存總量(包含內存碎片)

    • used_memory_peak redis 使用的內存總量峰值


    總結

    以上是生活随笔為你收集整理的Redis 实战之主从复制、高可用、分布式的全部內容,希望文章能夠幫你解決所遇到的問題。

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