Redis 集群配置 Docker 配置 集群 扩缩容

Redis 集群

Redis 集群

简介由于数据量过大,单个Master复制集难以承担,因此需要对多个复制集进行集群,形成水平扩展每个复制集只负责存储整个数据集的一部分,这就是Redis的集群,其作用是提供在多个Redis节点间共享数据的程序集。
image-20240125162209545

**效果:**Redis集群是一个提供在多个Redis节点间共享数据的程序集,Redis集群可以支持多个Master

image-20240125162606082

作用

  1. Redis?集群支特多个Master,每个Masterl又可以挂载多个Slave
  2. 由于Cluster自带Sentinel的故障转移机制,内置了高可用的支持,无需再去使用哨兵功能
  3. 客户端与Rdis的节点连接,不再需要连接集群中所有的节点,只需要任意连接集群中的一个可用节点即可
  4. 槽位so负责分配到各个物理服务节点,由对应的集群来负责维护节点、插槽和数据之间的关系

概念

Redis 处理方案

hash 槽位 slot

Redis集群投有使用一致性hash而是引入了哈希槽的概念
Redis集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽.集群的每个节点负责部分hash槽,
举个例子,比如当前集群有3个节点那么:

image-20240125164427866

分片

分片是什么使用Redis集群时我们会将存储的数据分散到多台redis机器上,这称为分片。简言之,集群中的每个Redis实例都被认为是整个数据的一个分片。
如何找到给定key的分片为了找到给定key的分片,我们对key进行CRC16(key)算法处理并通过对总分片数量取模。然后,使用确定性哈希函数,这意味着给定的key将多次始终映射到同一个分片,我们可以推断将来读取特定key的位置。
为什么要这样做这种结构很容易添加或者删除节点.比如如果我想新添加个节点D,我需要从节点A,B,C中得部分槽到D上.如果我想移除节点A,需要将A中的槽移到B和C节点上,然后将没有任何槽的A节点从集群中移除即可.由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态
其他处理方案
  1. Hash 取余

    image-20240125165416284

    更多操作2亿条记录就是2亿个k,v,我们单机不行必须要分布式多机,假设有3台机器构成一个集群,用户每次读写操作都是根据公式:hash(key) % N个机器台数,计算出哈希值,用来决定数据映射到哪一个节点上。

    优点: 简单粗暴,直接有效,只需要预估好数据规划好节点,例如3台、8台、10台,就能保证一段时间的数据支撑。使用Hash算法让固定的一部分请求落到同一台服务器上,这样每台服务器固定处理一部分请求(并维护这些请求的信息),起到负载均衡+分而治之的作用。

    缺点: 当 Redis 服务器扩容或是缩容的时候需要改边 计算公式 hash(key) % ? 。这个时候及可能无法与之前存储的数据所计算出来的位置保持一致。这都好说保证不改变数量就可以,但是如果 机器宕机了呢 对应位置的数据将无法进行存取。

  2. 一致性HASH

    (1 构建hash环

    一致性哈希环

    一致性哈希算法必然有个hash函数并按照算法产生hash值,这个算法的所有可能哈希值会构成一个全量集,这个集合可以成为一个hash空间[0,2^32-1],这个是一个线性空间,但是在算法中,我们通过适当的逻辑控制将它首尾相连(0 = 2^32),这样让它逻辑上形成了一个环形空间。

    它也是按照使用取模的方法,前面笔记介绍的节点取模法是对节点(服务器)的数量进行取模。而一致性Hash算法是对232取模,简单来说,一致性Hash算法将整个哈希值空间组织成一个虚拟的圆环,如假设某哈希函数H的值空间为0-232-1(即哈希值是一个32位无符号整形),整个哈希环如下图:整个空间按顺时针方向组织,圆环的正上方的点代表0,0点右侧的第一个点代表1,以此类推,2、3、4、……直到232-1,也就是说0点左侧的第一个点代表232-1, 0和232-1在零点中方向重合,我们把这个由232个点组成的圆环称为Hash环。

    image-20240125170510918

    (2 节点映射

    将集群中各个IP节点映射到环上的某一个位置。

    将各个服务器使用Hash进行一个哈希,具体可以选择服务器的IP或主机名作为关键字进行哈希,这样每台机器就能确定其在哈希环上的位置。假如4个节点NodeA、B、C、D,经过IP地址的哈希函数计算(hash(ip)),使用IP地址哈希后在环空间的位置如下:

    image-20240125170605537

    (3 落建服务器

    当我们需要存储一个kv键值对时,首先计算key的hash值,hash(key),将这个key使用相同的函数Hash计算出哈希值并确定此数据在环上的位置,从此位置沿环顺时针“行走”,第一台遇到的服务器就是其应该定位到的服务器,并将该键值对存储在该节点上。

    如我们有Object A、Object B、Object C、Object D四个数据对象,经过哈希计算后,在环空间上的位置如下:根据一致性Hash算法,数据A会被定为到Node A上,B被定为到Node B上,C被定为到Node C上,D被定为到Node D上。

    image-20240125170810702

    (4 优缺点

    优点 1健壮性

    假设Node C宕机,可以看到此时对象A、B、D不会受到影响。一般的,在一致性Hash算法中,如果一台服务器不可用,则受影响的数据仅仅是此服务器到其环空间中前一台服务器(即沿着逆时针方向行走遇到的第一台服务器)之间数据,其它不会受到影响。简单说,就是C挂了,受到影响的只是B、C之间的数据且这些数据会转移到D进行存储。

    image-20240125170943911

    优点 2易扩展

    数据量增加了,需要增加一台节点NodeX,X的位置在A和B之间,那收到影响的也就是A到X之间的数据,重新把A到X的数据录入到X上即可,不会导致hash取余全部数据重新洗牌。

    image-20240125171132223

    缺点:数据倾斜

    一致性Hash算法在服务节点太少时,容易因为节点分布不均匀而造成数据倾斜(被缓存的对象大部分集中缓存在某一台服务器上)问题,

    例如系统中只有两台服务器:

    image-20240125171405375

  3. Hash槽

Redis 集群中内置了 16384 个哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。当需要在 Redis 集群中放置一个 key-value时,redis先对key使用crc16算法算出一个结果然后用结果对16384求余数[ CRC16(key) % 16384],这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,也就是映射到某个节点上。如下代码,key之A 、B在Node2, key之C落在Node3上

在 Redis 增加删除的时候只需要对 Redis 集群中的部分槽位进行重新分配到其他的 Redis机器上面即可,宕机了使用该机器的 slaver。

image-20240125171447593

为什么只有16384个槽位?

(1)如果槽位为65536,发送心跳信息的消息头达8k,发送的心跳包过于庞大。

在消息头中最占空间的是myslots[CLUSTER_SLOTS/8]。 当槽位为65536时,这块的大小是: 65536÷8÷1024=8kb

在消息头中最占空间的是myslots[CLUSTER_SLOTS/8]。 当槽位为16384时,这块的大小是: 16384÷8÷1024=2kb

因为每秒钟,redis节点需要发送一定数量的ping消息作为心跳包,如果槽位为65536,这个ping消息的消息头太大了,浪费带宽。

(2)redis的集群主节点数量基本不可能超过1000个。

集群节点越多,心跳包的消息体内携带的数据越多。如果节点过1000个,也会导致网络拥堵。因此redis作者不建议redis cluster节点数量超过1000个。 那么,对于节点数在1000以内的redis cluster集群,16384个槽位够用了。没有必要拓展到65536个。

(3)槽位越小,节点少的情况下,压缩比高,容易传输

Redis主节点的配置信息中它所负责的哈希槽是通过一张bitmap的形式来保存的,在传输过程中会对bitmap进行压缩,但是如果bitmap的填充率slots / N很高的话(N表示节点数),bitmap的压缩率就很低。 如果节点数很少,而哈希槽数量很多的话,bitmap的压缩率就很低。

注意:要使 Docker 与 Redis 集群兼容,您需要使用 Docker 的主机组网模式

搭建集群

练习一下docker compose

  1. 编写 docker-compose.yml

    version: '3.1'
    services:
      # redis6379配置
      redis6379:
        image: redis:7.0.12
        container_name: redis_6379
         ports:
          - 6379:6379 # rediis端口
          - 16379:16379 # 集群节点通讯接口在对外设置的端口基础上+10000
        restart: always
        network_mode: "host"
        # 配置和数据的数据卷映射
        volumes:
          - /home/redis/cluster_6379.conf:/etc/redis/cluster.conf
          - /home/redis/data:/data
        command: ["redis-server", "/etc/redis/cluster.conf"]
       # redis6380配置
      redis6380:
        image: redis:7.0.12
        container_name: redis_6380
         ports:
          - 6380:6380 # rediis端口
          - 16380:16380 # 集群节点通讯接口在对外设置的端口基础上+10000
        restart: always
        network_mode: "host"
        # 配置和数据的数据卷映射
        volumes:
          - /home/redis/cluster_6380.conf:/etc/redis/cluster.conf
          - /home/redis/data:/data
        command: ["redis-server", "/etc/redis/cluster.conf"]
      # redis6381配置
      redis6381:
        image: redis:7.0.12
        container_name: redis_6381
         ports:
          - 6381:6381 # rediis端口
          - 16381:16381 # 集群节点通讯接口在对外设置的端口基础上+10000
        restart: always
        network_mode: "host"
        # 配置和数据的数据卷映射
        volumes:
          - /home/redis/cluster_6381.conf:/etc/redis/cluster.conf
          - /home/redis/data:/data
        command: ["redis-server", "/etc/redis/cluster.conf"]
       # redis6382配置
      redis6382:
        image: redis:7.0.12
        container_name: redis_6382
         ports:
          - 6382:6382 # rediis端口
          - 16382:16382 # 集群节点通讯接口在对外设置的端口基础上+10000
        restart: always
        network_mode: "host"
        # 配置和数据的数据卷映射
        volumes:
          - /home/redis/cluster_6382.conf:/etc/redis/cluster.conf
          - /home/redis/data:/data
        command: ["redis-server", "/etc/redis/cluster.conf"]
          # redis6383配置
      redis6383:
        image: redis:7.0.12
        container_name: redis_6383
         ports:
          - 6383:6383 # rediis端口
          - 16383:16383 # 集群节点通讯接口在对外设置的端口基础上+10000
        restart: always
        network_mode: "host"
        # 配置和数据的数据卷映射
        volumes:
          - /home/redis/cluster_6383.conf:/etc/redis/cluster.conf
          - /home/redis/data:/data
        command: ["redis-server", "/etc/redis/cluster.conf"]
       # redis6384配置
      redis6384:
        image: redis:7.0.12
        container_name: redis_6384
         ports:
          - 6384:6384 # rediis端口
          - 16384:16384 # 集群节点通讯接口在对外设置的端口基础上+10000
        restart: always
        network_mode: "host"
        # 配置和数据的数据卷映射
        volumes:
          - /home/redis/cluster_6384.conf:/etc/redis/cluster.conf
          - /home/redis/data:/data
        command: ["redis-server", "/etc/redis/cluster.conf"]
    
  2. 编写cluster_${port}.conf 配置文件

    每个配置文件都一样的,记得修改端口和日志持久化等文件名

    容器数据卷的映射文件夹记得创建!!!!!!!!!! 我踩坑了,不去创建的话,容器有很大概率启动不起来

    ################################## NETWORK #####################################
    protected-mode no
    #要改
    port 6379   
    tcp-backlog 511
    timeout 0
    tcp-keepalive 300
    ################################# GENERAL #####################################
    daemonize no
    #要改
    pidfile /data/cluster/pid/cluter_6379.pid 
    loglevel notice
    #要改
    logfile "/data/cluster/log/cluster_6379.log" 
    databases 16
    always-show-logo no
    set-proc-title yes
    proc-title-template "{title} {listen-addr} {server-mode}"
    ################################ SNAPSHOTTING  ################################
    save 3600 1 300 100 60 5
    stop-writes-on-bgsave-error yes
    rdbcompression yes
    rdbchecksum yes
    dbfilename dump_6379.rdb
    rdb-del-sync-files yes
    dir /data 
    
    ################################# REPLICATION #################################
    #要改与${requirepass}一样
    masterauth 111111 
    replica-serve-stale-data yes
    replica-read-only yes
    repl-diskless-sync yes
    repl-diskless-sync-delay 5
    repl-diskless-sync-max-replicas 0
    repl-diskless-load disabled
    repl-disable-tcp-nodelay no
    replica-priority 100
    ################################## SECURITY ###################################
    acllog-max-len 128
    requirepass 111111
    ############################# LAZY FREEING ####################################
    lazyfree-lazy-eviction no
    lazyfree-lazy-expire no
    lazyfree-lazy-server-del no
    replica-lazy-flush no
    lazyfree-lazy-user-del no
    lazyfree-lazy-user-flush no
    ############################ KERNEL OOM CONTROL ##############################
    oom-score-adj no
    oom-score-adj-values 0 200 800
    #################### KERNEL transparent hugepage CONTROL ######################
    disable-thp yes
    ############################## APPEND ONLY MODE ###############################
    appendonly yes
    #看心情改
    appendfilename "appendonly_cluster_6379.aof"  
     #看心情改
    appenddirname "cluster_appendonlydir"   
    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
    aof-timestamp-enabled no
    ################################ REDIS CLUSTER  ###############################
    cluster-enabled yes
    #看心情改
    cluster-config-file nodes-6379.conf 
    ################################## 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-listpack-entries 512
    hash-max-listpack-value 64
    list-max-listpack-size -2
    list-compress-depth 0
    set-max-intset-entries 512
    zset-max-listpack-entries 128
    zset-max-listpack-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
    jemalloc-bg-thread yes
    

    启动成功!

    image-20240126140120580

  3. 配置集群

    随便连接上一个 redis 机器 执行以下命令
    –cluster-replicas 1 意思是每台机器有一台 slaver

    改用自己的ip 和 端口 还有密码

    redis-cli -a 111111 --cluster create --cluster-replicas 1 43.138.25.182:6379 43.138.25.182:6380 43.138.25.182:6381 43.138.25.182:6382 43.138.25.182:6383 43.138.25.182:6384
    

    image-20240126143341284

    验证!

    使用正常连接方法连接集群时 部分 key 无法添加 因为分槽的原因 这个 key 可能不是当前 redis 机器可以存储的 使用集群方式连接则可以解决,下面测试中设置 k1 时提示槽位时 12706 需要移动到6381的机器上执行

    redis-cli -a <连接密码> -p <redis机器端口> -c 后面的-c表示集群连接

    image-20240126144006794

Stream On Error: Connection is closed 踩坑!

我在使用 Another Redis Desktop Manager客户端 连接redis集群报错 Stream On Error: Connection is closed

处理:修改node.conf

在node.conf中自动生成的 ip 是内网 ip 改成外网的就可以了

image-20240126150116864

Redis 集群扩缩容

reids 集群常用命令

  1. info replication查看主从信息
  2. cluster info 查看集群状态配置信息
  3. cluster nodes 查看集群节点信息
缩容
  1. 移除 slaver 节点机器

    # 命令:redis-cli -a 密码 --cluster del-node ip:从机端口 从机6384节点ID
     redis-cli -a 111111 --cluster del-node 43.138.25.182:6384 7cefe2b448b9876d7c095568a86cbbef5aaa155d
    

    image-20240126151859036

  2. 清空并分配 slot 数据槽

    redis-cli -a 111111 --cluster reshard 43.138.25.182:6381
    

    第一次输入的是移动的数量,第二次输入接受的id,第三次输入输出源(也就是清空的redis 的 id ,回车在输入done)

  3. 移除master

    # 命令:redis-cli -a 密码 --cluster del-node ip:从机端口 从机6381节点ID
    redis-cli -a 111111 --cluster del-node 43.138.25.182:6381 0e1a6339e2dc1f9ee2e47d2a46eb8a99b22b955d
    

    删除之后查看节点发现之前的6381 的槽位全在 6379上面

    image-20240126153637681

扩容
  1. 添加新的master

     #将新增的6387作为master节点加入原有集群 6387 就是将要作为master新增节点 6381 就是原来集群节点里面的领路人,相当于6387拜拜6381的码头从而找到组织加入集群
    #redis-cli -a 密码 --cluster add-node 自己实际IP地址:6387 自己实际IP地址:6381
    
    redis-cli -a 111111 --cluster add-node 43.138.25.182:6381 43.138.25.182:6379
    

    image-20240126160735535

  2. 分配slot给新的master(和上面一样的)

    redis-cli -a 111111 --cluster reshard 43.138.25.182:6381
    
  3. 分配新的slaver给新的master

    #命令:redis-cli -a 密码 --cluster add-node ip:新slave端口 ip:新master端口 --cluster-slave --cluster-master-id 新主机节点ID
    redis-cli -a 111111 --cluster  add-node 43.138.25.182:6384 43.138.25.182:6381 --cluster-slave --cluster-master-id 0e1a6339e2dc1f9ee2e47d2a46eb8a99b22b955d
    

    image-20240126163132167

    分配完成!6379对应6382 ,6381对应6384 ,6382对应6383

  • 11
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值