[003-02-10].第10节:Docker环境下搭建Redis主从复制架构

我的博客大纲
我的后端学习大纲
我的Redis学习大纲


1.cluster(集群)模式-docker版 哈希槽分区进行亿级数据存储

1.1.面试题:1~2亿条数据需要缓存,请问如何设计这个存储案例

  • 1.回答:单机单台100%不可能,肯定是使用Redis,对数据进行分布式存储,那在这分布式环境中,亿级的数据怎么进行存储,怎么进行查询,redis如何落地,有如下三种解决方案
    • 哈希取余分区
    • 一致性哈希算法分区
    • 哈希槽分区

2.三种解决方案的介绍:

2.1.哈希取余分区:

a.什么是哈希取余:

b.优点:

  • 1.简单粗暴,直接有效,只需要预估好数据,规划好节点,就能保证一段时间内的数据支撑。使用Hash算法,可以让固定的一部分请求落在同一台服务器上,这样每台服务器就处理一些固定的请求,起到负载均衡和分而治之的作用

c.缺点:

  • 原来规划好的节点,进行扩容或者缩容就比较麻烦了,不管扩缩,每次数据变动导致节点有变动,映射关系需要重新进行计算,在服务器个数固定不变时没有问题,如果需要弹性扩容或故障停机的情况下,原来的取模公式就会发生变化:Hash(key)/3会变成Hash(key) /?。此时地址经过取余运算的结果将发生很大变化,根据公式获取的服务器也会变得不可控。某个redis机器宕机了,由于台数数量变化,会导致hash取余全部数据重新洗牌。

2.2.一致性哈希算法分区:

a.是什么:

  • 1.一致性哈希算法在1997年由麻省理工学院中提出的,设计目标是为了解决上述分布式缓存数据变动和映射问题,某个机器宕机了,分母数量改变了,自然取余数不OK了。

b.能干嘛:

  • 1.提出一致性Hash解决方案。目的是当服务器个数发生变动时,尽量减少影响客户端到服务器的映射关系

c.实现步骤

  • 1.步骤1:算法构建一致性哈希环
    • 一致性哈希算法必然有个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环
  • 2.步骤2:服务器IP节点映射:
    • 集群中各个IP节点映射到环上的某一个位置
    • 将各个服务器使用Hash进行一个哈希,具体可以选择服务器的IP或主机名作为关键字进行哈希,这样每台机器就能确定其在哈希环上的位置。假如4个节点NodeA、B、C、D,经过IP地址的哈希函数计算(hash(ip)),使用IP地址哈希后在环空间的位置如下:
  • 3.步骤3:key落到服务器的落键规则:
    • 当我们需要存储一个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上。

d.优点

  • 1.一致性哈希算法的容错性:容错性假设Node C宕机,可以看到此时对象A、B、D不会受到影响,只有C对象被重定位到Node D。一般的,在一致性Hash算法中,如果一台服务器不可用,则受影响的数据仅仅是此服务器到其环空间中前一台服务器(即沿着逆时针方向行走遇到的第一台服务器)之间数据,其它不会受到影响。简单说,就是C挂了,受到影响的只是B、C之间的数据,并且这些数据会转移到D进行存储。
  • 2.一致性哈希算法的扩展性: 扩展性数据量增加了,需要增加一台节点NodeX,X的位置在A和B之间,那收到影响的也就是A到X之间的数据,重新把A到X的数据录入到X上即可,不会导致hash取余全部数据重新洗牌。

e.缺点

  • 1.一致性哈希算法的数据倾斜问题: Hash环的数据倾斜问题一致性Hash算法在服务节点太少时,容易因为节点分布不均匀而造成数据倾斜(被缓存的对象大部分集中缓存在某一台服务器上)问题,例如系统中只有两台服务器

f.总结:

  • 1.为了在节点数目发生改变时尽可能少的迁移数据 将所有的存储节点排列在收尾相接的Hash环上,每个key在计算Hash后会顺时针找到临近的存储节点存放。而当有节点加入或退出时仅影响该节点在Hash环上顺时针相邻的后续节点。
  • 优点加入和删除节点只影响哈希环中顺时针方向的相邻的节点,对其他节点无影响
  • 缺点 数据的分布和节点的位置有关,因为这些节点不是均匀的分布在哈希环上的,所以数据在进行存储时达不到均匀分布的效果。

2.3.哈希槽分区(常用)

a.什么是哈希槽:

  • 哈希槽实质就是一个数组数组[0,2^14 -1]形成hash slot空间

b.哈希槽能干什么:

  • 哈希槽解决均匀分配的问题,在数据和节点之间又加入了一层,把这层称为哈希槽(slot),用于管理数据和节点之间的关系,现在就相当于节点上放的是槽,槽里放的是数据
  • 解决的是粒度问题,相当于把粒度变大了,这样便于数据移动。
  • 哈希解决的是映射问题,使用key的哈希值来计算所在的槽,便于数据分配

c.多少个Hash槽:

  • 1.一个集群只能有16384个槽,编号0-16383(0-2^14-1)。这些槽会分配给集群中的所有主节点,分配策略没有要求。可以指定哪些编号的槽分配给哪个主节点。集群会记录节点和槽的对应关系。解决了节点和槽的关系后,接下来就需要对key求哈希值,然后对16384取余,余数是几key就落入对应的槽里。slot = CRC16(key) % 16384以槽为单位移动数据,因为槽的数目是固定的,处理起来比较容易,这样数据移动问题就解决了。
  • 2.哈希槽计算:
    • Redis 集群中内置了 16384 个哈希槽redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。当需要在 Redis 集群中放置一个 key-value时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,也就是映射到某个节点上。如下代码,key之A 、B在Node2, key之C落在Node3上

3.搭建Redis的3主3从的redis集群扩缩容配置案例架构:

3.1.搭建3主3从集群配置:

  • 1.架构图

  • 2.关闭防火墙 + 启动docker后台服务

  • 3.新建6个Docker实例:

    shell 复制代码
    docker run -d --name redis-node-1 --net host --privileged=true -v /data/redis/share/redis-node-1:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6381 
    
    docker run -d --name redis-node-2 --net host --privileged=true -v /data/redis/share/redis-node-2:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6382 
    
    docker run -d --name redis-node-3 --net host --privileged=true -v /data/redis/share/redis-node-3:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6383 
    
    docker run -d --name redis-node-4 --net host --privileged=true -v /data/redis/share/redis-node-4:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6384 
    
    docker run -d --name redis-node-5 --net host --privileged=true -v /data/redis/share/redis-node-5:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6385 
    
    docker run -d --name redis-node-6 --net host --privileged=true -v /data/redis/share/redis-node-6:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6386
  • 4.进入容器redis-one并为6台机器构建集群关系:
    • 假设是进入1号机:docker exec -it redis-node-1 /bin/bash
    • 构建主从关系的命令:cluster-replicas 1 表示为每个master创建一个slave节点
clike 复制代码
//注意,进入docker容器后才能执行一下命令,且注意自己的真实IP地址
redis-cli --cluster create 192.168.111.147:6381 192.168.111.147:6382 192.168.111.147:6383 192.168.111.147:6384 192.168.111.147:6385 192.168.111.147:6386 --cluster-replicas 1 
  • 5.链接进入6381作为切入点,查看集群状态
    • cluster info
    • cluster nodes

3.2.主从容错切换迁移案例:

a. 数据读写存储:

a1.启动6机构成的集群并通过exec进入
  • 1.进入6381机器:
  • 2.存储k-v测试:其原因是存储的key不在6381所属槽位,但是又不能自动分配到别的redis槽位上,其原因是目前是集群环境,使用的启动并不正确,是单机版的命令,应该是改成集群版命令。
  • 3.重启进入redis:
  • 4.查看集群信息:

b.容错切换迁移:

b1.主6381和从机切换,先停止主机6381
  • 1.停止6381机器:
b2.再次查看集群信息:发现6384机器变成了主机
b3.先还原之前的3主3从
  • 先启6381:docker start redis-node-1
  • 再停6385:docker stop redis-node-5
  • 再启6385:docker start redis-node-5
b4.查看集群状态:

3.3.主从扩容案例:

3主3从变成4主4从

a.新建6387、6388两个节点+新建后启动+查看是否8节点

shell 复制代码
docker run -d --name redis-node-7 --net host --privileged=true -v /data/redis/share/redis-node-7:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6387

docker run -d --name redis-node-8 --net host --privileged=true -v /data/redis/share/redis-node-8:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6388docker 

b.进入6387容器实例内部

  • 1.docker exec -it redis-node-7 /bin/bash

a.将新增的6387节点(空槽号)作为master节点加入原集群

  • 1.将新增的6387作为master节点加入集群:redis-cli --cluster add-node自己实际IP地址:6387 自己实际IP地址:6381

6387 就是将要作为master新增节点6381 就是原来集群节点里面的领路人,相当于6387拜拜6381的码头从而找到组织加入集群

c.检查集群情况第1次:

d.重新分派槽号:


e.检查集群情况第2次:

  • 1.检查命令:
  • 2.发现是每个节点分给第四台主机上:重新分配成本太高,所以前3家各自匀出来一部分,从6381/6382/6383三个旧节点分别匀出1364个坑位给新节点6387

f.为主节点6387分配从节点6388:

g.检查集群情况第3次:


3.4.主从缩容案例:

a.目的:6387和6388下线

b.检查集群情况,获得6388的节点ID

c.从集群中将4号从节点6388删除

d.将6387的槽号清空,重新分配,本例是将清出来的槽号都给6381


e.检查集群情况第二次:

f.将6387删除:

g.检查集群情况第三次:

相关推荐
小马爱打代码7 小时前
Redis 集群方案详解:主从复制、哨兵、脑裂、分片集群和哈希槽
数据库·redis·哈希算法
Irene19919 小时前
Win11 自动更新导致 Docker Desktop 无法正常启动,Oracle SQL Developer 启动时报错
docker·更新
darkdragonking12 小时前
OpenEuler 22.03 ,以docker ce 安装 Milvus 及可视化工具
docker·容器·milvus
我是一颗柠檬12 小时前
【Redis】发布订阅与消息队列Day8(2026年)
数据库·redis·后端·缓存
sukioe12 小时前
Redis 持久化+高可用详解:RDB/AOF/混合/主从/哨兵/集群
数据库·redis·缓存
我叫张土豆13 小时前
V100 显卡部署 Qwen3-ASR-1.7B 语音识别模型(vLLM + Docker 完整教程)
docker·语音识别·vllm
真上帝的左手14 小时前
11. 容器化 vs 虚拟化-K8s-工作负载实战
云原生·容器·kubernetes
XWalnut14 小时前
Redis从入门到精通
数据库·redis·缓存
极客先躯15 小时前
高级java每日一道面试题-2026年01月18日-实战篇[Docker]-如何清理仓库中的旧镜像?
java·运维·docker·容器
木雷坞17 小时前
Docker Hub、GHCR、Quay 混在一起后,镜像源要分开测
运维·docker