docker小白第九天

docker小白第九天

安装redis集群

cluster(集群)模式-docker版本,哈希槽分区进行亿级数据存储。如果1~2亿条数据需要缓存,请问如何设计这个存储案例。单机存储是不可能的,需要分布式存储,如果使用redis又该如何部署。

哈希取余分区

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

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

一致性哈希算法分区

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

三大步骤:

  • 算法构建一致性哈希环
  • 服务器lP节点映射
  • key落到服务器的落键规则

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

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

2、IP节点映射:

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

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上。

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

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

哈希槽分区

哈希槽实质就是一个数组,数组0,(2\^14)-1形成hash slot空间。解决缓存数据均匀分配的问题,在数据和节点之间又加入了一层,把这层称为哈希槽(slot),用于管理数据和节点之间的关系,现在就相当于节点node上放的是槽,槽里放的是数据。

槽解决的是粒度问题,相当于把粒度变大了,这样便于数据移动(即一堆数据算做一类,以前是一个数据算做一类)。哈希解决的是映射问题,使用key的哈希值来计算所在的槽,便于数据分配。节点数1000以内的redis集群,槽位最多16384个。这些槽会分配给集群中的所有主节点,分配策略没有要求。可以指定哪些编号的槽分配给哪个主节点。集群会记录节点和槽的对应关系。解决了节点和槽的关系后,接下来就需要对key求哈希值,然后对16384取余,余数是几key就落入对应的槽里。slot =CRC16(key) % 16384。以槽为单位移动数据,因为槽的数目是固定的,处理起来比较容易,这样数据移动问题就解决了。

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

3主3从配置redis集群

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

先关闭防火墙,并确认dokcer是启动状态的

bash 复制代码
systemctl stop firewalld
systemctl start docker

然后开启新建redis集群容器

bash 复制代码
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
# --cluster-enabled yes 是开启集群配置
# 创建并运行docker容器实例 docker run
# 容器名字--name redis-node-1
# 使用宿主机的IP和端口,默认--net host
# 获取宿主机root用户权限 --privileged=true
# 挂载容器卷,-v 宿主机地址:docker内部地址地
# redis镜像和版本号redis:6.0.8
# 开启持久化 --appendonly yes
# redis端口号--port 6381

依次修改节点的数字和端口的数字,执行六次新建容器命令

bash 复制代码
docker ps

查看启动后的容器

进入redis节点1的容器命令行配置,注意其中的ip要换为自己的真实ip地址。--cluster-replicas 1表示为每个master创建一个slave节点。

bash 复制代码
docker exec -it redis-node-1 /bin/bash
redis-cli --cluster create 192.168.0.175:6381 192.168.0.175:6382 192.168.0.175:6383 192.168.0.175:6384 192.168.0.175:6385 192.168.0.175:6386 --cluster-replicas 1

可以看到,自动创建了三个hash slots(哈希槽),分配给了三个主redis节点,另外新建了三个备redis节点,与主节点对应。

在redis节点1的命令行,查看集群状态

bash 复制代码
redis-cli -p 6381
# 连接到节点1的端口
cluster info
# 查看集群信息
bash 复制代码
cluster nodes
# 更详细的3主3从集群信息

注意,这里的主从对应的序号,是不固定的,是随机的,有可能1号机与4号机,做主从关系,有可能1号机与5号机,做主从关系。

redis集群读写error,优化路由案例

bash 复制代码
# 进入第一个redis节点的容器命令行
docker exec -it redis-node-1 /bin/bash
# 客户端进入redis节点1,通过端口6381
redis-cli -p 6381
# 输入命令查看里边是否有数据
keys *

可以看到里边数据为空。

输入以下命令存储数据,发现会报错。是因为经过哈希运算,需要分配给该数据的槽位是12706,超过了redis节点1的最大槽位5460,通过端口6383判断,该数据应该被存至redis节点3。

bash 复制代码
set k1 v1

可以通过修改连接集群的命令,新增数据。不通过redis-cli -p 6381这种单机的方式连接,造成数据只访问redis节点1。为防止数据自动跳转路由失效,加参数-c,代表使用的是集群环境,并新增两个key,测试

bash 复制代码
# 在redis节点1容器的命令行,输入如下命令
redis-cli -p 6381 -c
set k1 v1
set k2 v2

可以看到都存储成功了,并且经过哈希计算后,若待分配的槽位不在节点1时,自动redicrt重定向数据到对应的节点。

bash 复制代码
# 在节点1容器的命令行界面,查看集群信息
redis-cli --cluster check 192.168.0.175:6381

可以看到刚刚存储的两个键值对,分别在哪。还有其他一些集群信息。

相关推荐
用户03284722207014 小时前
如何搭建本地yum源(上)
运维
武子康15 小时前
调查研究-183 Apple container:Mac 上用轻量 VM 跑 Linux 容器,Swift 会改写本地容器体验吗?
docker·容器·apple
大树884 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠4 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质4 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
Inhand陈工4 天前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
Alsn864 天前
等待学习-学习目录:Docker 容器安全攻防
学习·安全·docker
酣大智4 天前
ARP代理--工作原理
运维·网络·arp·arp代理
shushangyun_4 天前
2026年快消品B2B系统推荐:支持终端门店订货、促销政策自动化的工具?
java·运维·网络·数据库·人工智能·spring·自动化
施努卡机器视觉4 天前
SNK施努卡侧滑门锁上滑轮总成自动化装配线,从零件到组件,全流程精密制造方案
运维·自动化·制造