为什么要用redis-cluster

并发问题

redis官方生成可以达到 10万/每秒,每秒执行10万条命令
假如业务需要每秒100万的命令执行呢?


数据量太大

一台服务器内存正常是16~256G,假如你的业务需要500G内存,

新浪微博作为世界上最大的redis存储,就超过1TB的数据,去哪买这么大的内存条?各大公司有自己的解决方案,推出各自的集群功能,核心思想都是将数据分片(sharding)存储在多个redis实例中,每一片就是一个redis实例。



各大企业集群方案:
twemproxy由Twitter开源
Codis由豌豆荚开发,基于GO和C开发
redis-cluster官方3.0版本后的集群方案



解决方案如下

  1、配置一个超级牛逼的计算机,超大内存,超强cpu,但是问题是。。。。

redis 百万数据存储多长时间 redis百万级 需要多少内存_数据

  2.正确的应该是考虑分布式,加机器,把数据分到不同的位置,分摊集中式的压力,一堆机器做一件事

redis 百万数据存储多长时间 redis百万级 需要多少内存_redis_02

客户端分片

redis3.0集群采用P2P模式,完全去中心化,将redis所有的key分成了16384个槽位,每个redis实例负责一部分slot,集群中的所有信息通过节点数据交换而更新。



redis实例集群主要思想是将redis数据的key进行散列,通过hash函数特定的key会映射到指定的redis节点上



数据分布原理图

redis 百万数据存储多长时间 redis百万级 需要多少内存_ruby_03

数据分布理论

分布式数据库首要解决把整个数据集按照分区规则映射到多个节点的问题,即把数据集划分到多个节点上,每个节点负责整个数据的一个子集。

常见的分区规则有哈希分区和顺序分区。Redis Cluster采用哈希分区规则,因此接下来会讨论哈希分区规则。

  • 节点取余分区
  • 一致性哈希分区
  • 虚拟槽分区(redis-cluster采用的方式)

顺序分区

redis 百万数据存储多长时间 redis百万级 需要多少内存_ruby_04

哈希分区

redis 百万数据存储多长时间 redis百万级 需要多少内存_数据_05

例如按照节点取余的方式,分三个节点

1~100的数据对3取余,可以分为三类

  • 余数为0
  • 余数为1
  • 余数为2

那么同样的分4个节点就是hash(key)%4

节点取余的优点是简单,客户端分片直接是哈希+取余

虚拟槽分区 

Redis Cluster采用虚拟槽分区



虚拟槽分区巧妙地使用了哈希空间,使用分散度良好的哈希函数把所有的数据映射到一个固定范围内的整数集合,整数定义为槽(slot)。

Redis Cluster槽的范围是0 ~ 16383。

槽是集群内数据管理和迁移的基本单位。采用大范围的槽的主要目的是为了方便数据的拆分和集群的扩展,

每个节点负责一定数量的槽。



redis 百万数据存储多长时间 redis百万级 需要多少内存_redis_06

搭建redis cluster

搭建集群分为几部

  • 准备节点(几匹马儿)
  • 节点通信(几匹马儿分配主从)
  • 分配槽位给节点(slot分配给马儿)

redis-cluster集群架构



多个服务端,负责读写,彼此通信,redis指定了16384个槽。

多匹马儿,负责运输数据,马儿分配16384个槽位,管理数据。

ruby的脚本自动就把分配槽位这事做了



环境准备,6个redis数据库节点



redis-7000.conf
redis-7001.conf
redis-7002.conf
redis-7003.conf
redis-7004.conf
redis-7005.conf



每个配置文件的内容,仅仅是端口的不同7000~7005

配置内容如下:



port 7000
daemonize yes
dir "/opt/redis/data/7000"
logfile "7000.log"
dbfilename "dump-7000.rdb"
cluster-enabled yes   #开启集群模式
cluster-config-file nodes-7000.conf  #集群内部的配置文件
cluster-require-full-coverage no 
#redis cluster需要16384个slot都正常的时候才能对外提供服务,换句话说,只要任何一个slot异常那么整个cluster不对外提供服务。 因此生产环境一般为no



快速生成6个节点的配置文件



mkdir -p /opt/redis/data/{7000,7001,7002,7003,7004,7005}
sed "s/7000/7001/g" redis-7000.conf > redis-7001.conf 
sed "s/7000/7002/g" redis-7000.conf > redis-7002.conf 
sed "s/7000/7003/g" redis-7000.conf > redis-7003.conf 
sed "s/7000/7004/g" redis-7000.conf > redis-7004.conf 
sed "s/7000/7005/g" redis-7000.conf > redis-7005.conf



启动6个redis节点



redis-server redis-7000.conf 
redis-server redis-7001.conf 
redis-server redis-7002.conf 
redis-server redis-7003.conf 
redis-server redis-7004.conf 
redis-server redis-7005.conf



基于ruby语言的脚本工具自动分配槽位

分配槽位,开始放入数据,查看数据流向



1.下载ruby的解释器
    wget https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.1.tar.gz

2.解压缩ruby的源码包
    tar -zxvf ruby-2.3.1.tar.gz
3.进入ruby的源码包目录,编译三部曲
    cd ruby-2.3.1
    ./configure --prefix=/opt/ruby231
    make && make install

3.配置ruby的环境变量
    /opt/ruby231/bin
    vim /etc/profile 
    写入PATH=""

4.读取这个/etc/profile
    source /etc/profile

5.下载ruby操作redis的模块
wget http://rubygems.org/downloads/redis-3.3.0.gem
#安装ruby操作redis的模块
gem install -l redis-3.3.0.gem


6.一键分配redis集群的槽位
#查找一下这个命令的绝对路径
find  / -name redis-trib.rb
#这个数字 1 代表,每个redis主库,只有一个redis从库 
/opt/redis-4.0.10/src/redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005



开启集群状态功能

开启了集群状态功能后,登录数据库,查看数据写入流向



/opt/redis-4.0.10/src/redis-trib.rb add-node --slave 127.0.0.1:7003 127.0.0.1:7000



查看集群状态:
redis-cli -p 7000 cluster info
redis-cli -p 7001 cluster info
redis-cli -p 7002 cluster info
redis-cli -p 7003 cluster info
redis-cli -p 7004 cluster info
redis-cli -p 7005 cluster info



测试写入集群数据,登录集群必须使用redis-cli -c -p 7000必须加上-c参数

redis 百万数据存储多长时间 redis百万级 需要多少内存_数据_07

各节点之间的数据共享,但是数据的保存位置是根据算法决定的;意思就是我们在哪个节点查询数据都可以查得到,只是数据得保存位置不一

redis 百万数据存储多长时间 redis百万级 需要多少内存_数据_08

redis-cluster自带哨兵功能会自动监测主节点是否宕机!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

下面得可以忽略不写

哨兵检测主节点状态

防止redis-cluster主节点故障,可以搭配 redis-cluster +  redis-sentinel ,用哨兵检测主节点状态,当主节点宕机,自动切换从节点为新的主库



1.redis-sentinel配置方式如下,检测三个主节点7000  7001  7002
        port 27379
        dir "/var/redis/data"
        logfile "26379.log"
        sentinel monitor master1 127.0.0.1 7000 2  
        sentinel monitor master2 127.0.0.1 7001 2  
        sentinel monitor master3 127.0.0.1 7002 2  

        sentinel down-after-milliseconds master1 30000  
        sentinel down-after-milliseconds master2 30000  
        sentinel down-after-milliseconds master3 30000  

        sentinel parallel-syncs master1 1  
        sentinel parallel-syncs master2 1  
        sentinel parallel-syncs master3 1  

        sentinel failover-timeout master1 180000  
        sentinel failover-timeout master2 180000  
        sentinel failover-timeout master3 180000  

    2.启动哨兵,检测cluster的主节点
    redis-sentinel redis-26379.conf
    
    3.杀死redis-cluster的主节点,查看从节点状态(是否自动重启),可以运行多个从节点,保证数据安全



工作原理:

redis客户端任意访问一个redis实例,如果数据不在该实例中,通过重定向引导客户端访问所需要的redis实例