Hi,大家好,我是抢老婆酸奶的小肥仔。
今天我们直接进入主题,来说说docker安装redis的一些相关操作。
1、单机版
1.1 拉去镜像
使用docker pull拉取redis镜像,以redis:6.0.8版本为例。
docker pull redis:6.0.8
1.2 创建文件夹并创建配置文件
在home目录下创建redis目录,创建redis的配置文件redis.conf,并拷贝redis的原始配置内容。
配置事项:与linux安装配置一样。
mkdir -p /home/redis
vim /home/redis/redis.conf
原始配置文件内容,可以在网上找。
1、开启redis验证,即设置密码(可选项)
requirepass 123456
2、允许外部连接redis
即将bind 127.0.0.1
进行注释,修改protected-mode
为no或指定绑定ip。
# bind 127.0.0.1
protected-mode no
3、daemonize no
将daemonize yes进行注释或daemonize no设置。
daemonize no
# daenmonize yes
因为该设置和docker run 中-d参数冲突,会导致容器启动失败。
4、开启redis数据持久化(可选项)
appendonly yes
1.3 创建容器
使用docker run命令创建redis的容器。
docker run \
--restart=always \
--privileged=true \
-p 6379:6379 --name redis \
-v /home/redis/redis.conf:/etc/redis/redis.conf \
-v /home/redis/data:/data \
-d redis:6.0.8 redis-server /etc/redis/redis.conf
此时用命令查询,可以看到redis的容器。
1.4客户端连接redis
验证redis是否能够被客户端正常连接,并使用。
将配置文件中的将保护模式更改为no,即protected-mode yes改成protected-mode no。
protected-mode yes 改为 protected-mode no
使用客户端连接redis,我这边使用的是DbGate进行连接,改工具既可以连接mysql也可以连接redis,mongodb等,界面与其他客户端大同小异。
Connection-type:连接类型,选择redis,
Server:redis服务的ip
Port:端口
User:用户
Password:密码
点击连接,出现如下界面,即能看到redis的16个数据库,则表示连接成功。
至此,单机版的redis部署完成。
2、集群版
在搭建集群时,一般会涉及到节点的分区,在redis中节点分区有三种常见算法:哈希取余算法,一致性哈希算法,哈希槽算法。我们来分别 看下这些算法。
2.1 分区算法
2…1.1 哈希取余算法
算法描述:hash(key) %N:key:redis存储的键名,N:redis集群的机器台数。即通过对存储的键名进行hash计算,对机器台数进行取余来决定存储在那台机器上。
优点:1、简单直接
,只需要规划好节点,就能支持一段书简的数据支撑。
2、负载均衡,分而治之
:Hash算法能让固定的一部分数据落到同一台机器上,每台机器能固定处理一部分请求。
缺点:对扩容/缩容不友好
:节点的变动会导致N的变化,取模运算的结果会发生很大变化,导致根据公式获取的服务器变得不可控。导致hash取余的全部数据都要进行重新计算
2.1.2 一致性哈希算法
算法背景:为了解决哈希算法中存在的分布式缓存数据变动和映射问题
。即当服务器数量发生变化时,尽量减少影响到客户端与服务器端的映射关系
算法步骤:1、构建一致性哈希环
:
一致性哈希环,即有个hash函数并按照算法产生hash值,然后将产生的哈希值构建成一个全量集,这个集合的hash空间[0,2^32-1],再通过适当逻辑将其首尾相连构成环形空间。一致性hash环是按照数字顺时针进行组织。如图:
一致性hash算法:是对2^32 取模,即将hash取余算法中的机器数N换成2^32即可。
2、服务器IP节点映射
:服务器(IP或主机名)进行hash计算,从而确定其在hash环上的位置。
3、落键规则
:即key落到服务器上的规则,即将要存储的数据key进行hash计算(hash(key)),然后沿环顺时针“行走”,遇到的第一台服务器就是该key定位到的服务器,并将该键值存储到该服务器上。
例如:在hash环上有4个服务器,需要保存键值数据kv,经过key的hash计算,发现匹配第一台到第二台服务器中间,则顺时针找到第二台服务器,并将kv保存到该服务器上。如图:
优点:1、容错性
:即解决了哈希取余算法中存在缺点,当某个节点服务器宕机时,该服务器上的数据则会顺时针移动到下一个节点服务器。例如上面说的server-2宕机后,保存在server-2上的k-v数据则会顺时针保存到server-3节点服务器上。
2、扩展性
:当需要添加新节点服务器时,通过hash计算落在某两个节点服务器之间,此时受影响的只有当前两个节点服务器。
缺点:数据倾斜问题
,当节点比较少时,容易因为节点服务器分布不均匀而导致数据倾斜。
2.1.3 hash槽分区
算法描述:为了解决一致性hash算法中的数据倾斜问题。其相当于是一个数组,数组[0,2^14 - 1]形成的hash slot空间。相当于在数据和节点服务器之间又加入一层,在这一层就是哈希槽(slot),用于管理数据和节点之间的关系, 此时节点服务器中存放的是槽,而槽里面放的是数据。
槽解决的是粒度问题,相当于把粒度变大,这样便于数据移动。
哈希解决的是映射问题,使用key的哈希值来计算所在槽,便于数据分配。
redis集群只有16384个槽。
经典问题:为什么redis集群的最大槽数是16384个?
答:redis集群没有使用一致性hash算法而是引入哈希槽的概念,CRC16算法产生的hash值有16bit,可以产生2^16 = 65536
值,但是为了心跳方便和数据传输最大化,因此才用2^14=16384
个。
1、心跳过大,造成宽带浪费
:如果槽个数是65536时,其心跳信息通过myslots[CLUSTER_SLOTS/8] = 65536/8/1024 = 8kb
计算会达到8k,显得过于庞大,redis在每秒一定数据量的ping消息作为心跳时,就会造成宽带浪费。
2、主节点数量基本不可能超过1000个
,当redis集群主节点数不可能超过1000个时,集群节点越多,心跳包的消息体携带的数据就越多。如果集群主节点数超过1000个时,就会造成网络拥堵。因此redis作者不建议redis集群主节点超过1000个,对于1000主节点以内的集群,16384个槽位足够使用,没必要扩展到65536个。
3、槽位越小,节点少的情况下压缩比越高,容易传输
,主节点配置信息中它所负责的哈希槽是通过一张bitmap的形式来保存,在传输过程中会对bitmap进行压缩,但是如果bitmap的填充率slots/N(N节点数) 很高的话,bitmap的压缩率就很低,而哈希槽越多,节点越少,bitmap压缩率就越低。
Redis集群原理:即将16384个槽按照一定策略(可以指定编码的槽分配给主节点,也可以是redis集群自动分配)映射给主节点,当需要存储一个k-v时,redis先对key使用CRC16计算出一个结果,然后对16384取余,即slot = CRC16(key) % 16384
这样每个key都有对应一个在0到16383之间的哈希槽,也就能映射到某个节点上。
2.2 redis集群搭建
上面知道了redis分区的一些算法,下面我们来搭建一个3主3从的redis集群。
2.2.1 创建redis容器
搭建3主3从的集群,则需要创建6个容器。
# 启动第1台节点
docker run -d --name redis-master-6380 --net host --privileged=true -v /home/redis/cluster/master/6380:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6380
# 启动第2台节点
docker run -d --name redis-master-6381 --net host --privileged=true -v /home/redis/cluster/master/6381:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6381
# 启动第3台节点
docker run -d --name redis-master-6382 --net host --privileged=true -v /home/redis/cluster/master/6382:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6382
# 启动第4台节点
docker run -d --name redis-slave-6390 --net host --privileged=true -v /home/redis/cluster/slave/6390:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6390
# 启动第5台节点
docker run -d --name redis-master-6391 --net host --privileged=true -v /home/redis/cluster/slave/6391:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6391
# 启动第6台节点
docker run -d --name redis-master-6392 --net host --privileged=true -v /home/redis/cluster/slave/6392:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6392
参数说明:
--net host
使用宿主机的IP和端口,默认
--cluster-enabled yes
开启redis集群
--appendonly yes
开启redis持久化
--port 6381
配置redis端口号
执行完上述命令后,此时6台容器已执行完成,使用docker ps -a查看容器。
2.2.2 构建主从关系
主要是通过redis-cli --cluster create进行构建,后面加上6个redis的ip:端口。
# 宿主机IP:端口
redis-cli --cluster create IP:端口 IP:端口 --cluster-replicas 1
--cluster-replicas 1
:表示集群关联是一对一,即为每一个主节点创建一个从节点。
--cluster create
:集群创建。
IP:端口
:即我们需要创建集群的所有redis节点,例如我们需要构建6个节点的集群,则需要添加6个节点的ip和端口
选择进入一个我们认定的redis主节点容器执行该命令。
docker exec-it redis-master-6380 /bin/bash
执行上述命令。
# 宿主机IP:端口
redis-cli --cluster create 192.168.132.113:6380 192.168.132.113:6381 192.168.132.113:6382 192.168.132.113:6390 192.168.132.113:6391 192.168.132.113:6392 --cluster-replicas 1
执行完当前命令后,我们会看到如下信息:
redis自主帮我们分配了主节点,从节点。同时也完成了一对一的设置,如主节点6380挂载的从节点是6390。
细心的小伙伴会发现上面截图中会有一串警告:
通过翻译我们应该也知道是因为从节点与主节点都使用了相同的IP,这个警告可以直接忽略。
执行完命令后,会出现Can I set the above configuration? (type 'yes' to accept)
输入yes,redis会向其他节点发送信息加入集群,并真正地分配哈希槽。
2.2.3 查看集群状态
进入主节点容器,例如上面看到的6380.
docker exec -it redis-master-6380 /bin/bash
然后使用redis-cli连接其他主节点,例如连接6381节点
redis-cli -p 6381
此时是能正常进入该节点。
使用cluster info查看集群状态。
cluster info
此时会看到一些哈希槽的相关信息,例如cluster_slotexits_assigned:16384
:表示哈希槽的个数,cluster_slots_ok
:16384:状态良好的哈希槽个数等等。
cluster nodes
可以查看集群节点的信息。
进入任一节点容器,输入以下命令可以检查集群信息。
# 输入任意一台主节点地址都可以进行集群检查
redis-cli --cluster check 192.168.xxx.xxx:6380
2.3 集群读写
由于集群中每个节点都只是会分配到16384个哈希槽的一部分,在当前节点保存数据时,计算出key的值可能不在当前节点所分配的哈希槽范围内,此时如果仅仅使用redis-cli -p IP:端口
进行节点连接进行操作的话就会出现问题。
此时就会报错提醒:(eroor)MOVED,也就是计算哈希槽在其他节点。
解决:要解决上述问题,只需要在连接节点时在命令后面加上-c即可
redis-cli -p IP:端口 -c
2.4 主从扩容
在现实使用redis集群时,有时候会因为空间不足,而需要对集群进行扩容,例如我们的三注三从,扩容成四主四从。接下来我们来看下redis的扩容。
2.4.1 添加容器
既然是四主四从,那我们就再添加两个节点。即根据2.2.1来分别添加6383,6393两个节点。
# 启动第7台节点
docker run -d --name redis-master-6383 --net host --privileged=true -v /home/redis/cluster/master/6383:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6383
# 启动第8台节点
docker run -d --name redis-slave-6393 --net host --privileged=true -v /home/redis/cluster/master/6393:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6393
查看docker中redis的容器,发现已经创建了两个新的容器。
2.4.2 加入集群
将6383作为新的节点加入到集群中。
进入6383容器中
docker exec -it redis-master-6383 /bin/bash
将6383作为主节点加入到集群中
redis-cli --cluster add-node 192.168.xxx.xxx:6383 192.168.xxx.xxx:6380
add-node:即要加入主节点,如上面的6383,其后是已加入集群的主节点ip:端口。
查看当前集群情况
redis-cli --cluster check 192.168.xxx.xxx:6380
查看集群情况会发现,6383节点已加入集群,但是没有分配任何哈希槽,接下来则需要分配哈希槽。
2.4.3 分配哈希槽
执行如下命令:
redis-cli --cluster reshard 192.168.132.113:6380
执行完命令后,我们会看到如下询问:How many slots do you want to move (from 1 to 16384)?,即需要移动多少个槽点。
分配槽点的计算方法:slot = 16384/主机数
,如上面集群中存在4个主节点,则slot = 16384 / 4 = 4096,输入4096后,回车,则会出现:What is the receiving node ID?即需要分配槽点的节点Id,我们添加的是6383的节点,因此输入6383对应的节点id。
然后提示分配槽点的方式:
all:即从之前的主节点中,每一个都分配一部分给新加入的主节点。
down:即自己输入哪些节点分配槽点给新加入的主节点。
一般直接输入:all即可。redis自动开始从其他主节点移动槽点。
移动完成后,则需要继续执行计划,输入:yes
即可完成将移动的槽点移到新的主节点。
2.4.4 添加从节点
即将6393作为6383的从节点,加入到集群中,命令:
redis-cli --cluster add-node 192.168.132.113:6393 192.168.132.113:6383 --cluster-slave --cluster-master-id 主节点编码
查看节点信息,会发现6393已经作为6383的从节点,加入到集群中.
至此,完成了redis的主从扩容已完成。
2.5 主从缩容
有扩容,当然也有缩容,高峰期过后,我们需要将4主4从,改回3主3从,将添加的6383进行删除,下面我们来看看,redis的缩容。
具体步骤:1.删除从节点 2.移除主节点的哈希槽
2.5.1 获取编号
获取6383的编号,即需要删除节点的编号。进入集群任意主节点,然后检查集群,即可获取6383编号。
2.5.2 删除从节点
先将从节点6393进行删除
redis-cli --cluster del-node 192.168.132.113:6393 6393对应ID
2.5.3 重新分配哈希槽
即需要集群中的主节点上的哈希槽进行重新分配,使用一个其他主节点来接收分配后的哈希槽,命令如下:
#reshard任意集群的主节点,例如:6383主节点
redis-cli --cluster reshard 192.168.xxx.xxx:6383
输入当前命令后,输入需要移除的槽点数量,之前我们计算得到4096个槽点数,因此当前也需要输入4096,然后输入需要接收这些槽点的节点Id。
注:上面参数必须要清楚对应,否则无法进行哈希槽重新分配.
配置上述节点后,输入done
即可进行重新分配哈希槽.
此时会看到6383上的哈希槽已经被移除.
2.5.4 删除主节点
使用命令删除6383节点
redis-cli --cluster del-node IP:端口 节点编号
如果在没有移除哈希槽时进行删除节点则会报如下错误:
输入正确命令执行后,主节点被删除。
2.5.5 查看集群
再次查看集群,发现6383、6393已经被删除,完成了集群的缩容,恢复到3主3从。
docker安装redis就跟大家聊到这,如果觉得有用的话,记得点赞,收藏,关注哦。谢谢大家。