个人博客

redis集群搭建

一、简介

redis是一个开源的key value存储系统,在redis3.0之前只支持单例模式,在redis3.0之后才开始支持集群模式。一般情况下,哨兵模式已经能满足一般的生产需求,具备了redis服务的高可用性。但是当数据达到一台服务器存放不下的情况,主从模式或者哨兵模式就不能满足需求。这个时候就需要对数据进行分片,将数据存储到多个redis实例中,集群模式就能解决单机redis容量的问题。

redis集群是主从模式和哨兵模式的结合体,拥有主从复制和master节点重选功能,如果要搭建2副本3分片的集群,就需要6个redis实例。

启动redis集群也比较容易,只要在redis的配置文件中,配置上cluster-enabled yes即可启动为redis集群模式,每个集群至少要有3个master节点才能正常运行,因为为了实现集群的高可用,redis集群有一个投片容错机制,如果集群中超过半数节点认为某节点挂了,那才能确定某个节点是真的挂了。3个中挂了1个,另外2个同时检测到某节点挂了,才能超过半数,所以至少需要3个master节点。

一般主节点挂了,从节点会自动升级为主节点。如果redis集群中,某个主节点挂了,而且该主节点没有从节点,那么这个集群也就会挂了。因为集群内置了16384个slot(哈希槽),并且把这些slot平均分配到各个节点。当redis集群要存放一个数据时,redis会先对这个key进行哈希算法,然后该值进行16384求余得到一个结果,再把数据分配到指定的哈希槽中。所以一旦某一个节点的不能用了,该slot也就不能用了,那么redis集群就不能正常工作。

redis集群特点:

  • 多个redis节点网络互连,数据共享。
  • 所有节点都是一主一从(也可以是一主多从),其中从节点不提供服务,只是作为备份。
  • 不支持同时处理多个key(如MSET/MGET或pipeline),因为redis把key均匀分配到各个节点上,不同的key会分配到不同的哈希槽中。
  • 支持在线增加、删除节点。
  • 客户端可以连接任何一个主节点进行读写。

二、安装高版本redis

1,首先安装redis编译依赖的环境:

yum -y install make gcc*

2,下载redis:

wget http://download.redis.io/releases/redis-5.0.7.tar.gz

3,进入到redis目录

cd redis-5.0.7

4,编译安装redis:

make MALLOC=libc && make install

三、redis集群模式搭建

1,准备3台虚拟机,分别启动两个redis服务器:

192.168.1.202        端口:7001,7002
192.168.1.203        端口:7001,7002
192.168.1.204        端口:7001,7002

2,创建项目目录并复制redis.conf文件:

mkdir cluster_redis
cd cluster_redis
cp ../redis-5.0.7/redis.conf ./
cp redis.conf redis_7001.conf
cp redis.conf redis_7002.conf

3,修改redis配置文件:

在192.168.1.202服务器,先配置redis_7001.conf文件:

bind 0.0.0.0
port 7001
daemonize yes
pidfile "./redis_7001.pid"
logfile "./redis_7001.log"
dir "./data/redis_7001"
masterauth 123456
requirepass 123456
appendonly yes
cluster-enabled yes
cluster-config-file nodes_7001.conf
cluster-node-timeout 15000

再配置redis_7002.conf文件:

bind 0.0.0.0
port 7002
daemonize yes
pidfile "./redis_7002.pid"
logfile "./redis_7002.log"
dir "./data/redis_7002"
masterauth 123456
requirepass 123456
appendonly yes
cluster-enabled yes
cluster-config-file nodes_7002.conf
cluster-node-timeout 15000

其他两台服务器也是一样的配置,这里省略。

4,参数说明:

  • cluster-enabled yes:如果配置为yes则开启redis集群功能,此redis实例作为集群的一个节点,否则它就是一个普通的redis实例。
  • cluster-config-file nodes_7001.conf:这个文件不能人工编辑,它是集群自动维护的文件,主要用于记录集群中有哪些节点,它们的状态以及一些持久化参数等,方便在重启时恢复这些状态。
  • cluster-node-timeout 15000:这个是集群节点的超时时间,如果超过这个时间还是不可达,那就认为是故障,用它的从节点启动故障转移,升级为主节点。

5,创建数据保存目录:

mkdir -p ./data/redis_7001
mkdir -p ./data/redis_7002

其他两台服务器也创建相同的目录,这里省略。

6,启动redis服务:

redis-server redis_7001.conf
redis-server redis_7002.conf

7,创建集群:

如果redis版本比较低,则需要安装ruby,任意一台机器安装ruby即可。redis5.0版本则不需要安装ruby,直接创建集群。

redis-cli -a 123456 --cluster create 192.168.1.202:7001 192.168.1.202:7002 192.168.1.203:7001 192.168.1.203:7002 192.168.1.204:7001 192.168.1.204:7002 --cluster-replicas 1

picture

可以看到集群的信息:

192.168.1.202:7001是master,它的slave是192.168.1.202:7002;
192.168.1.203:7001是master,它的slave是192.168.1.203:7002;
192.168.1.204:7001是master,它的slave是192.168.1.204:7002;

自动生成nodes.conf,这里可以看到集群各个节点的信息:

vi data/redis_7001/nodes-7001.conf

picture

8,登录集群:

redis-cli -c -h 192.168.1.202 -p 7001 -a 123456                  # -c,使用集群方式登录

查看集群信息,使用CLUSTER INFO命令,得到下面的信息:

picture

查看节点信息,使用CLUSTER NODES命令,得到下面的信息:

picture

这里列出的内容和nodes.conf文件的内容相同。

现在,尝试写入数据,可以从返回的信息看到key存放在哪个节点:

picture

data1和data2在192.168.1.203:7001,data3在本机192.168.1.202:7001,“keys *"命令也只能看到本机的data3数据。同时在192.168.1.202:7001获取data2也是可以获取到值的,集群会自动跳转到192.168.1.203:7001获取到相应的key。

可以看出,redis集群是去中心化的,每个节点都是平等的,连接哪个节点都可以获取到数据。当然平等指的是master节点,不包括slave节点,slave节点不提供服务,只作为master的一个备份。

9,新增redis集群节点:

在192.168.1.202机器上新增配置文件redis_7003.conf:

bind 0.0.0.0
port 7003
daemonize yes
pidfile "/var/run/redis_7003.pid"
logfile "/usr/local/redis/cluster/redis_7003.log"
dir "/data/redis/cluster/redis_7003"
masterauth "123456"
requirepass "123456"
appendonly yes
cluster-enabled yes
cluster-config-file nodes_7003.conf
cluster-node-timeout 15000

并创建数据保存目录:

mkdir -p data/redis_7003

启动redis服务:

redis-server redis_7003

登录集群之后,使用CLUSTER MEET 192.168.1.202 7003命令增加新节点:

CLUSTER MEET 192.168.1.202 7003

同样可以再创建一个redis_7004,启动服务后添加入redis集群,这里就不重复展示。

最后我们看下现在集群中的redis节点信息:

picture

从节点信息里可以看到,这里新加的节点都是以master的身份加入到redis集群的,如果我们想要新增从节点,可以使用“cluster replicate ”命令指定当前节点为某节点的从节点,如:

redis-cli -c -h 192.168.1.202 -p 7004 -a 123456 cluster replicate 619623815413fef13f13f3184f50842157455c73

也可以登录redis集群之后,使用“CLUSTER REPLICATE ”命令更改当前节点为某节点的从节点:

CLUSTER REPLICATE 619623815413fef13f13f3184f50842157455c73

这时候在看看节点信息:

picture

10,删除redis集群节点:

登录redis集群之后,使用“CLUSTER FORGET ”命令,删除redis集群的节点,但不能删除当前node节点,也不能删除当前节点的master节点:

picture

也可以使用命令直接删除需要删除的节点:

redis-cli -a 123456 --cluster del-node 192.168.1.202:7004 b2e1352bd01537bacf75f2b0c50a08907e18cce1
redis-cli -a 123456 --cluster del-node 192.168.1.202:7003 619623815413fef13f13f3184f50842157455c73

四、redis集群命令

  • cluster info:打印集群信息。
  • cluster nodes:列出当前集群已知所有节点,以及这些节点的相关信息。
  • cluster meet :将IP和PORT所指定的节点添加到集群中,让它成为一份子。
  • cluster forget :将当前节点设置为node id指定的节点的从节点。
  • cluster saveconfig:将节点的配置文件保存到硬盘。
  • cluster slaves :列出node id所有从节点。
  • cluster set-config-epoch:强制设置configEpoch。
  • cluster addslots [slot...]:将一个或者多个槽指派给当前节点。
  • cluster delslots [slot...]:移除一个或者多个槽对当前节点的指派。
  • cluster flushslots:移除当前节点的所有槽,让当前节点变为空槽节点。
  • cluster setslots node :将槽指派给指定node id节点,如果该槽已经属性某个node id节点,那需要先删除再进行指派。
  • cluster setslots migrating :将本节点的槽迁移到node id节点上。
  • cluster setslots importing :从node id节点中导入槽到本节点。
  • cluster setslots stable:取消对槽的导入(import)或者迁移(migrate)。
  • cluster keyslot :计算key应该放在哪个槽上。
  • cluster countkeysinslot :返回槽目前包含的key的数量。
  • cluster getkeysinslot :返回count个槽中key。
  • cluster myid:放回节点ID。
  • cluster slots:返回节点负责的槽。
  • cluster reset:重置集群,慎用。

五、python操作redis集群

1,先安装python操作集群的库:

这里需要使用到redis-py-cluster,但是不要使用pip install redis-py-cluster安装最新的包,它会附带安装redis-3.0.1包,但是这两个包不兼容,会出现在找不到StrictRedisCluster的问题,这里推荐安装redis-py-cluster的1.3.6版本,它会自动安装reids-2.10.6,这两个版本是兼容的。可以使用命令:

pip install redis-py-cluster==1.3.6

这里也可以看别人在安装redis-py-cluster遇到的坑,可参考

然后创建一个python文件,写入以下代码测试:

from rediscluster import StrictRedisCluster

if __name__ == '__main__':
    try:
        # redis集群中的所有主结点(所有master结点)
        startup_nodes = [
            {'host': '192.168.1.202', 'port': '7001'},
            {'host': '192.168.1.203', 'port': '7001'},
            {'host': '192.168.1.204', 'port': '7001'},
        ]
        # 构建StrictRedisCluster对象
        src = StrictRedisCluster(startup_nodes=startup_nodes, password='123456', decode_responses=True)
        result = src.set('data5','test5') 
        print(result)  # True
        name = src.get('data5')
        print(name)
   except Exception as e:
        print(e)
相关标签
回到顶部