当前位置:网站首页 > 技术博客 > 正文

redis集群切片的三种方式




通过前面的文章由基础到进阶把redis相关知识都讲了一遍,今天来写redis系列最后一篇文章——分片集群;我们都知道,主从集群解决了单点故障的问题,但是并没有解决因数据量大而给服务端带来的压力问题,而分片集群刚好能够完美解决;分片集群就是在海量数据的情况下把redis数据打到不同的redis实例上来减轻单台服务的压力,分片集群的解决方案各种各样,本文从理论上把我所知道的大概都过一遍,然后介绍redis支持的集群模式,最后再根据两种代理服务部署一遍redis的集群


基于客户端的分片即redis集群部署好,每个实例存不同的数据,通过客户端的前置操作来决定数据到底应该到哪台实例,大概有以下几种思路

  • 描述:即set数据的时候据根据业务进行划分,比方说用户信息放一个redis实例,订单信息放一个实例
  • 优缺点:这种方式应该很少有人会用,虽说按业务区分了,但是业务之间可能会存在交叉,增加了查询的复杂度
  • 描述:set数据的时候用hash函数获取key的hash值然后对redis集群里的实例个数进行取模操作
  • 优缺点:虽说这种方式无论从复杂度还是效率上都还过的去,但是有个致命的缺点就是模数不能随意改变,一改变会涉及到整个集群的rehash,所以对redis的扩缩容很不友好
  • 描述:即通过随机函数每次随机访问redis实例
  • 优缺点:这种方式set数据倒是高效了但是set的数据几乎不能取出来,所以并不适用;
  • 描述:这种方式会抽象出一个哈希环出来,这个环上有足够多的点,每个redis的实例根据ip+端口(或者其他唯一标识)通过哈希函数计算出一个点位落在这个环上,每当有新数据进来时通过哈希计算出在环上的位置,然后顺时针方向找离自己最近的redis实例节点,然后就可以往这个节点设置数据,取数据同理;
  • 优点:这样做一定程度解决了redis集群扩缩容导致的rehash问题,以扩容为例,当redis新增一台实例时,按照上面的步骤首先会落在哈希环上某一点A,影响的数据只是A点逆时针方向到上一个redis节点区间内的数据,如下图:
    在这里插入图片描述
  • 缺点:当redis实例数量过少时,可能会出现数据分布不均匀的情况,即数据倾斜。例如,如果哈希环上的节点分布不均匀,某些节点可能会承担过多的数据存储任务,而其他节点则可能负载较轻;可以通过虚拟节点来解决,即将一个redis实例根据某一规则拓展出10个节点打到环上,这样命中就会变得均匀

通过以上客户端分片的解决方案,我们好像解决了数据容量的问题,但是引入了一个新的问题:通过客户端做分片的话,由于业务的需要理论上每个客户端都会连接redis集群中的每个实例,从而给实例带来了访问压力,所以客户端做分片的转发不是最优解;所以才有了基于代理的分片,即在客户端和redis集群之间架一个代理层,由代理层来做数据的分发,比较常用的代理层服务有twemproxy、predixy等;

redis官方使用的集群策略没有用上面总结的方法,而是引入的哈希槽的概念,Redis集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽.集群的每个节点负责一部分hash槽,举个例子,比如当前集群有3个节点,那么哈希槽分配如下:

  • 节点 A 包含 0 到 5500号哈希槽.
  • 节点 B 包含5501 到 11000 号哈希槽.
  • 节点 C 包含11001 到 16384号哈希槽.

这种结构很容易添加或者删除节点. 比如如果我想新添加个节点D, 我需要从节点 A, B, C中得部分槽到D上. 如果我想移除节点A,需要将A中的槽移到B和C节点上,然后将没有任何槽的A节点从集群中移除即可. 由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态.

twemproxy是由Twitter开源的一套代理分片服务,可以接受多个客户端的访问然后根据配置的算法将数据分配到不同的redis节点,再按原路返回;不支持redis的watch、multi等命令

  • 1、mkdir twemproxy 在/root目录创建一个twemproxy用来存放twemproxy的源码
  • 2、安装git yum install git
  • 3、克隆twemproxy的代码
    • git clone https://github.com/twitter/twemproxy.git
  • 4、进入源码目录,cd twemproxy
  • 5、安装automake和libtool
    • yum install automake libtool -y
  • 6、安装configure,执行autoreconf -fvi
  • 7、执行 https://blog.csdn.net/_/article/details/configure
  • 8、执行make编译源码,编译完正常会有可执行程序出现
  • 9、进入源码的/scripts目录,将配置文件拷贝至/etc/init.d/twemproxy目录
    • cp nutcracker.init /etc/init.d/twemproxy
  • 10、进入init.d文件, 执行chmod +x twemproxy给twemproxy赋权
  • 11、创建配置文件所在的目录
    • mkdir /etc/nutcracker
  • 12、进入源码安装目录的conf目录,将conf目录下的配置文件拷贝到11步创建的文件夹下
    • cd ~/soft/twemproxy/twemproxy/conf
    • cp https://blog.csdn.net/_/article/details/* /etc/nutcracker/
  • 13、进入源码安装目录的src目录,将编译完的可执行程序复制到/usr/bin目录下,这样在系统任意位置都可以运行nutcracker
    • cd ~/soft/twemproxy/twemproxy/src/
    • cp nutcracker /usr/bin
  • 14、进入nutcracker目录,修改配置文件
    • cd /etc/nutcracker/
    • cp nutcracker.yml nutcracker.yml.bak 稳妥起见,先备份
    • vi nutcracker.yml 编辑配置文件
  • 15、启动两个redis实例
    • redis-server ~/testRedis/6379.conf
    • redis-server ~/testRedis/6380.conf
  • 16、启动nutcracker
    • service twemproxy start
  • 17、启动redis客户端连接nutcracker对外暴露的端口
    • redis-cli -p 22121 连接成功后如图,即可对redis进行操作

    我们通过22121端口的代理就可以直接访问redis集群,可以设置数据,但是由于数据分治了,所以例如keys 、watch、multi等这种聚合的命令在代理里是不支持的;至此,通过twemproxy 代理的方式搭建的redis集群就完成了,客户端只需链接22121端口,至于后续的分片操作由代理服务进行转发

predixy也是一款redis的代理服务,其即支持redis sentinel又支持redis cluster,在group只有一个的情况下,其还支持watch、multi等指令

  • 1、在~/soft目录创建predixy目录并且进入,用于下载源码;
    • mkdir predixy
    • cd predixy
  • 2、下载源码包
    • wget https://github.com/joyieldInc/predixy/releases/download/1.0.5/predixy-1.0.5-bin-amd64-linux.tar.gz
  • 3、解压
    • tar xf predixy-1.0.5-bin-amd64-linux.tar.gz
  • 4、进入conf目录,编辑predixy.conf文件
    • vi predixy.conf
    • 将bind 127.0.0.1:7617的注释放开
    • 将Include try.conf注释,将Include sentinel.conf放开
  • 5、编辑sentinel.conf 文件
    • vi sentinel.conf
    • 将SentinelServerPool配置的注释放开,并按下图进行配置

Sentinels{}里填哨兵集群的ip和端口

Group表示redis分组,shard001表示分组名称;上图配置表示一个哨兵集群监控了两套redis的主从集群

注意:Group后面跟的名称需要与哨兵配置文件里的master名称一致

  • 6、根据5中的注意,所以我们现在需要去修改哨兵的配置文件,将其监控的master名称由默认的mymaster改为shard001,又因为我们需要哨兵监控两个主从集群,所以需要再加一个shard002的master配置,命令如下:
    • vi 26379.conf 、 vi 26380.conf 、 vi 26381.conf
    • 修改完的配置文件如下图

    注意:上图只截取了26379的配置,26380和81与79除了port外其余配置均一致

  • 7、启动哨兵集群
    • redis-server https://blog.csdn.net/_/article/details/26379.conf --sentinel
    • redis-server https://blog.csdn.net/_/article/details/26380.conf --sentinel
    • redis-server https://blog.csdn.net/_/article/details/26381.conf --sentinel
  • 8、任意位置创建文件夹test,在里面创建36379、80和46379、80的目录
    • 进入36379目录执行 redis-server --port 36379
    • 进入36380目录执行 redis-server --port 36380 --replicaof 127.0.0.1 36379追随36379

      这样一个主从集群就搭建起来了,46379和80与上面一致,只需更改对应端口即可,我这里就不再赘述了

    至此,哨兵集群与两套redis主从复制集群已启动完毕

  • 9、进入predixy安装的bin目录启动predixy
    • cd soft/predixy/predixy-1.0.5/bin
    • https://blog.csdn.net/_/article/details/predixy …/conf/predixy.conf
    • 启动成功如下图:
  • 10、用redis客户端测试

    虽然上面搭建废了九牛二虎之力,但是对客户端而言只需关注predixy对外暴露的服务连接即可:

    • redis-cli -p 7617

    连接成功后就可以操作redis了,predixy会自动分发到不同的redis集群中去;设置如图:

    • 然后连接36379可以发现,k1和设置了tag的key都分发到此了,如图:
    • 再连接46379,发现k2被分发到46379了

predixy只支持单group下的事务、watch等操作,我们这里配置了两个group所以不支持;但是如果只配置一个group的话那么能写的也只有一个master,就失去了分片集群的意义了


至此,redis系列学习的文章就全部结束了,后续有空我会抽时间再写一篇我此次面试中遇到的redis真题,顺便把前面漏的redis数据结构的底层实现给补上

  • 上一篇: ifconfig和ip a
  • 下一篇: jpa 原生sql
  • 版权声明


    相关文章:

  • ifconfig和ip a2025-03-16 10:00:59
  • 图形验证码到底有什么用2025-03-16 10:00:59
  • js数组删除2025-03-16 10:00:59
  • 交叉验证模型2025-03-16 10:00:59
  • android seekbar2025-03-16 10:00:59
  • jpa 原生sql2025-03-16 10:00:59
  • 位图索引和普通索引2025-03-16 10:00:59
  • ce认证检测机构联系方式2025-03-16 10:00:59
  • 面向对象设计的3个基本特征2025-03-16 10:00:59
  • cwe(CWE Top 25 2021. Что такое, с чем едят и чем полезен при статическом анализе?)2025-03-16 10:00:59