Redis(三) redis集群
一、 redis哨兵模式的缺点
- 问题一 : 横向扩展不方便 , 一旦扩展 , 无论代码结构多么简单, 都需要修改
- 问题二 : 散列分布式算法是hash一致性 , 无论多少的数据迁移都会造成扩展集群和收缩集群时必须要做数据迁移 。
- redis在3.0 版本时引入redis集群的技术 , 解决以上问题
- 无论如何扩展redis集群 , 代码都无需修改 , 继续使用旧配置
- redis集群支持手动迁移数据(只需啊要一个命令即可) , 而且无需知道底层算法 , 维护人员手动迁移数据 , 而且可以控制迁移数量
二、 redis集群架构
- 对于客户端,连接redis集群无需配置全部结点的ip和端口最少配置一个就可以,分布式不是代码维护而是集群内部管理数据分布
- 内部数据(key-value)是根据0~16383的槽道传递的
- 内部数据的重定向
- 使用key值进行哈希取模 , 得到的就是槽道号 , 结点会判断这个槽道号是不是自己所管理的, 如果是 , 则保存 ; 如果不是 , 则数据从定向
- 这样缓存结构在扩容或收缩时 , 就解决了需要手动修改代码的问题
- 手动迁移数据
- 在集群中所有的key真正映射关系和redis节点本身无关,只和槽道号有关,需要数据迁移时,不能直接对key-value对数据操作,而是将槽道进行重新分配(reshard)集群中的所有数据将会根据重新计算的槽道管理内容进行重新转发保存(迁移的过程类似于修改数据加锁的过程,不能再迁移时进行数据操作)
- 重新分配 槽道后 ,所有的对应当前迁移这些槽道号的key-value数据将会 根据槽道的重新分配进行转发存储
- 在redis中可以调用迁移命令来reshard数据槽道号 , 所以无需代码客户端调用程序重新分配数据 。
- 在集群中所有的key真正映射关系和redis节点本身无关,只和槽道号有关,需要数据迁移时,不能直接对key-value对数据操作,而是将槽道进行重新分配(reshard)集群中的所有数据将会根据重新计算的槽道管理内容进行重新转发保存(迁移的过程类似于修改数据加锁的过程,不能再迁移时进行数据操作)
三 、 搭建redis集群
- 安装ruby : 因为集群命令需要ruby环境的支持
- 如果有外网连接 , 则直接使用yum install ruby 命令
, 但是要注意版本 , 必须使用2.3版本以上
- 检查安装是否成功
- 检查安装是否成功
- 如果没有外网连接 , 则需要实现准备安装包 , 上传到linux中后使用tar -xvf ruby资源 解压 (或者有网的情况下 wget “https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.1.tar.gz”)
- 进入ruby目录 , 执行编译
- 编译安装 使用make && make install
- 进入ruby目录 , 执行编译
- 如果有外网连接 , 则直接使用yum install ruby 命令
- 安装gems
- RubyGems(简称gems)是一个用于对ruby组将进行打包的ruby打包系统 , ,它提供一个分发ruby程序和库的标准格式 , 还提供一个管理程序的包安装工具 , 是一种技术支持
- 使用命令 yum install rubygems 安装
- 安装redis接口包 : gem install redis
- 检查安装情况 ruby -v
- 安装redis 略(在redis一中)
- 要求reids的版本必须是3.0以上
创建集群节点
- 创建不同redis节点对应的管理目录
修改配置文redis.conf件并上传到指定目录
P61 bind 127.0.0.1//默认ip为127.0.0.1改为其他节点机器可访问的ip 注释掉bind P80 protected-mode no //yes修改为no P84 port 7000 //端口7000 P128 daemonize yes //后台运行 P150 pidfile /var/run/redis_7000.pid //pidfile文件对应7000 当大量的进程启动后,很难通过ps -ef|grep redis直接寻找你需要操作的进程的pid P163 logfile=7000/redis.log //相对路径,启动时在redis的根目录 P593 appendonly yes P721 cluster-enabled yes //开启集群 P729 cluster-config-file nodes_7000.conf //集群的配置 P735 cluster-node-timeout 15000 //请求超时 默认15秒,可自行设置
- 修改完成并上传完成后检查
分别启动这些 结点
redis-server 7000/redis7000.conf redis-server 7001/redis7001.conf redis-server 7002/redis7002.conf redis-server 7003/redis7003.conf redis-server 7004/redis7004.conf redis-server 7005/redis7005.conf
- 检查是否启动陈宫
- 但是现在所有的结点并不是说结群的状态
- 在src目录下有个redis-trib.rb 文件, 这个就是ruby语言写的命令文件 。
执行创建集群命令 。
./redis-trib.rb 如果我使用的是./说明当前的/etc/profile中没有对PATH进行 ./的配置,所有不在环境变量中的命令文件需要到对应目录调用./启动 在src目录下执行 #./redis-trib.rb create --replicas 1 106.75.74.254:7000 106.75.74.254:7001 106.75.74.254:7002 106.75.74.254:7003 106.75.74.254:7004 106.75.74.254:7005 ./redis-trib.rb create 新节点ip:端口 旧ip:端口 解释下, --replicas 1 表示 自动为每一个master节点分配一个slave节点 上面有6个节点,程序会按照一定规则生成 3个master(主)3个slave(从)
防火墙一定要关闭 , 否则会创建失效
创建成功
- 创建不同redis节点对应的管理目录
- 测试集群:
- 登录
这里需要注意 ,如果使用原有的命令(没有 -c) , 则表示单节点登录 , 没有集群效果
- 查看集群效果
epoch是一个逻辑计算时间, 与节点的所有变化都有关 , cluster_current_epoch:6 , 代表当前集群的逻辑计算时间 , 数字越大 , 表示操作或配置越新 , 整个集群的之歌值都是一致的 。 cluster_my_epoch:1表示当前节点的逻辑计算时间 。
- 查看集群节点
这里会显示节点ID 、 ip:port(节点的ip和端口号) 、 flags(节点的角色 , 如: master 、 slave 、 myself) 、 以及状态 。
- 如果一个节点是一个从节点 , 则跟在flags后面的将是主节点的ID
- master 后有一个值的范围 , 这个就是该主节点管理的hash槽道 , 默认在集群开启时将槽道平均分配到个master节点。
- 登录
- 高可用验证:
- 停掉一个主节点的进程(kill 掉 7000)
- 然后登陆集群查看集群节点
- 启动停掉的结点会自动拼成slave加入
- 创建并启动新节点7007 , 7006
- 执行添加结点命令 , 将结点添加在集群中
前面的是需要被添加的结点 , 后面是集群中已有的任意节点
- 可能会出现以下问题
需要查看当前节点中是否存在key
如果被天剑的结点中已有数据 , 将会添加集群失败 , 这是为了防止数据冲突, 不允许带有数据的结点动态添加到集群中 。使用flushdb命令将7006中的数据清空
- 进入进群查看结点状态
- 指定 添加为某个主节点的从节点(如果不指定 , 默认添加为从节点)
–slave和–master-id 必须同时使用才能起到指定master添加节点的作用
- 添加从节点 (实现创建并开启7007)
- 执行添加节点成为某一台主节点的从节点命令 (–slave 指定当前节点以从节点的角色添加到集群中 , –master-id 指定从节点添加时挂载的主节点的ID)
新的master要起作用需要保存缓存数据 , 数据实际是被槽道控制 , 所以添加主节点后需要迁移槽道来为新的主节点分配槽道
- 根据提示操作
- 问你需要移动多少槽道
- 接收移动的槽道的结点的ID(7006ID)
- 从哪里迁移槽道?
- 如果从指定的多个结点迁移 ,则依次粘贴对应的结点的ID , 必须是主节点 , 添加完成之后输入done 表示分配计算结束
- 如果需要所有主节点平均分配 , 则直接输入all
- 你确定这样的分片计划么 yes
- 查看cluster nodes 发现7006已经有了从其他主结点迁移过来的槽道了
- 问你需要移动多少槽道
- 删除节点
- 删除从节点 (无数据直接删除)
- 主节点不能直接删除 , 需要将槽道全部移除之后再删除
将槽道移到7003
这里必须写7006的id
这里只从7006移除槽道所以写完7006ID后输入done结束输入
- 完成之后调用删除节点命令删除节点
- 查看集群节点状态 , 7006 和他的从节点7007都消失了
- 删除从节点 (无数据直接删除)
- 停掉一个主节点的进程(kill 掉 7000)
四、 引出的问题
- 集群的扩展思路分析
- 维护人员可以人为地控制当前节点上的槽道 , 从而人为的控制数据倾斜
- 问题: 每一个节点是如何知道自己管理的槽道有哪些?
- 问题: 如果不是自己管理的槽道 , 那么将数据转发到那个节点 ?
解答: 每一个节点都维护着两个信息
- 一个是16384为的位序列
- 一个是所有节点共享的16384个元素的数组
要知道本节点维护的槽道号, 只需要访问本节点中的这个16384位的为序列即可
在集群中所有节点共享一个16384个元素的数组 , 数组元素保存节点信息;集群中每个节点的数组信息一致
reshard分片过程中,位序列和数组的变化 位序列先计算,变化,每一个变动槽道号的master节点的位序列; 例子;7001 400-500;然后将这101个槽道挪走了挪到7002 位序列变化 400-500节点从1编程0;数组信息 400-500的元素清空; 7002 接收400-500;然后位序列中的400-500位从0变成1;将共享数组的400-500元素赋值,自己的值 主从从复制,主宕从顶的特点; 主从复制;复制主节点的key-value数据 位序列为0 共享数组也存在从节点; 主从替换;7001主,7003从 位序列不一样,数据一样,数组一样; 7003顶替的过程;将数组进行分析,是7001的获取下标,计算位序列;根据位序列修改数组,将位序列是1的下标对应更新数组元素;数组同步复制; 数据的重新计算: 1 主从替换时,数据完全不用动 2 reshard过程完成后,所有key重新计算,根据转发逻辑,改转发的转发,改保留的保留