Redis5版本集群搭建

Stella981
• 阅读 481

一、简介

1.1 Redis是什么

Redis是一个开源的,使用ANSI C 编写,高性能的Key-Value的NoSQL数据库。

1.2 Redis特点

(1)基于内存

(2)可持久化数据

(3)具有丰富的数据结构类型,适应非关系型数据的存储需求

(4)支持绝大多数主流开发语言,如C、C++、Java、Python、R、JavaScript等。

(5)支持集群模式,高效、稳定。

1.3 数据模型(重点)

(1)键值对形式。

(2)Redis的数据结构类型,指的就是Redis值的结构类型。

1.4 Redis作用

(1)本质是数据库,能存储数据。

Redis能灵活处理非关系型数据的读、写问题,是对MySQL等关系型数据库的补充。

新浪微博就是使用Redis集群做数据库。

(2)缓存数据。

所谓缓存,就是将数据加载到内存中后直接使用,而不是每次都通过IO流从磁盘上读取。好处:读写效率高。

而Redis则是将数据直接存储在内存中,只有当内存空间不足时,将部分数据持久化到磁盘上。

二、安装

1.1 说明

Redis官方只提供了源码,并没有提供经过编译之后的安装包。
因此,安装Redis,要先编译、后安装。(即源码安装方式)

1.2 redis安装步骤

# 安装步骤
cd /usr/local/src
wget http://download.redis.io/releases/redis-5.0.4.tar.gz
tar -zxv -f redis-5.0.4.tar.gz 
cd /usr/local/src/redis-5.0.4/
make MALLOC=libc (或者直接make,不用./configure)
make install (安装到指定目录:make PREFIX=/usr/local/redis install,不指定的话默认安装到/usr/local/bin目录下,也可以执行该步骤,也就是安装)

# 不安装的话命令执行文件路径是:/usr/local/src/redis-5.0.4/src

# 配置文件:/usr/local/src/redis-5.0.4/redis.conf

# 优化配置,使用root账号操作
# vim /etc/sysctl.conf
vm.overcommit_memory = 1
net.core.somaxconn = 2048
# sysctl -p

# echo never > /sys/kernel/mm/transparent_hugepage/enabled
# vim /etc/rc.d/rc.local
if test -f /sys/kernel/mm/transparent_hugepage/enabled; then
   echo never > /sys/kernel/mm/transparent_hugepage/enabled
fi

if test -f /sys/kernel/mm/transparent_hugepage/defrag; then
   echo never > /sys/kernel/mm/transparent_hugepage/defrag
fi
# chmod +x /etc/rc.d/rc.local

# vim /etc/security/limits.conf
* soft nofile 65535
* hard nofile 65535


# 启动
[sandu@bogon ~]# ./src/redis-server ./redis.conf
1270:C 02 Aug 2019 16:27:19.274 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
1270:C 02 Aug 2019 16:27:19.275 # Redis version=5.0.4, bits=64, commit=00000000, modified=0, pid=1270, just started
1270:C 02 Aug 2019 16:27:19.275 # Configuration loaded
                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 5.0.4 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                   
 (    '      ,       .-`  | `,    )     Running in standalone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 1270
  `-._    `-._  `-./  _.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |           http://redis.io        
  `-._    `-._`-.__.-'_.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'                                               

1270:M 02 Aug 2019 16:27:19.277 # Server initialized
1270:M 02 Aug 2019 16:27:19.277 * Ready to accept connections


# 使用自带的客户端连接,默认没有密码直接连接
[sandu@bogon ~]# ./src/redis-cli 
127.0.0.1:6379> ping # 检测redis服务是否启动
PONG
127.0.0.1:6379> set a 1111
OK
127.0.0.1:6379> get a
"1111"
127.0.0.1:6379> quit # 退出

# 密码连接
# redis-cli -h host  -p port -a password
[sandu@bogon ~]# ./src/redis-cli 
127.0.0.1:6379> auth foobar2000
OK
127.0.0.1:6379> set b 222222
OK
127.0.0.1:6379> get b
"222222"
127.0.0.1:6379> exit

1.3 redis.conf常用配置说明

  • bind:允许访问该redis的主机

  • protected-mode:保护模式,默认开启。若设置外部网络连接redis服务,设置方式如下:

    1、关闭protected-mode模式,此时外部网络可以直接访问

    2、开启protected-mode保护模式,需配置bind ip或者设置访问密码,或者bind ip和密码都设置

  • requirepass:设置密码

  • databases:Redis默认有16个数据库,寻址角标从0开始。默认连接db0。客户端使用select命令,切换数据库

  • port :指定redis的服务端口,默认6379.

  • daemonize:Redis默认关闭后台进程模式,改成yes,redis服务在后台启动。

  • loglevel :日志等级

  • logfile:Redis日志输出目录,默认不输出日志到文件。

  • dbfilename:指定数据持久化的文件名

  • dir :指定数据持久化的文件存放目录,也是集群node.con文件存放目录

  • cluster-enabled:是否启用集群

  • cluster-config-file:集群文件

1.4 redis启动方式

  1. 直接启动

进入redis根目录,执行命令,加上‘&’号使redis以后台程序方式运行

 ./src/redis-server &
  1. 通过指定配置文件启动
    可以为redis服务启动指定配置文件,例如配置为/etc/redis/6379.conf

    ./src/redis-server /etc/redis/6379.conf

进入redis根目录,输入命令,如果更改了端口,使用redis-cli客户端连接时,也需要指定端口,例如:

redis-cli -p 6380
# redis-cli -h host  -p port -a password
  1. 使用redis启动脚本设置开机自启动,有问题,只能启动和停止,不能查看状态,也不能重载,还有就是关闭的话貌似关不掉,不予考虑该脚本

启动脚本 redis_init_script 位于位于Redis的 /utils/ 目录下,redis_init_script脚本代码如下:

#!/bin/sh
#
# Simple Redis init.d script conceived to work on Linux systems
# as it does use of the /proc filesystem.

# chkconfig:   2345 90 10

### BEGIN INIT INFO
# Provides:     redis_6379
# Default-Start:        2 3 4 5
# Default-Stop:         0 1 6
# Short-Description:    Redis data structure server
# Description:          Redis data structure server. See https://redis.io
### END INIT INFO

#redis服务器监听的端口
REDISPORT=6379

#服务端所处位置
EXEC=/usr/local/bin/redis-server

#客户端位置
CLIEXEC=/usr/local/bin/redis-cli

#redis的PID文件位置,根据实际情况修改
PIDFILE=/var/run/redis_${REDISPORT}.pid

#redis的配置文件位置,需将${REDISPORT}修改为文件名
CONF="/etc/redis/${REDISPORT}.conf"

case "$1" in
    start)
        if [ -f $PIDFILE ]
        then
                echo "$PIDFILE exists, process is already running or crashed"
        else
                echo "Starting Redis server..."
                $EXEC $CONF
        fi
        ;;
    stop)
        if [ ! -f $PIDFILE ]
        then
                echo "$PIDFILE does not exist, process is not running"
        else
                PID=$(cat $PIDFILE)
                echo "Stopping ..."
                $CLIEXEC -p $REDISPORT shutdown
                while [ -x /proc/${PID} ]
                do
                    echo "Waiting for Redis to shutdown ..."
                    sleep 1
                done
                echo "Redis stopped"
        fi
        ;;
    *)
        echo "Please use start or stop as first argument"
        ;;
esac

将启动脚本复制到/etc/init.d目录下,本例将启动脚本命名为redisd(通常都以d结尾表示是后台自启动服务)

cd 
cp redis_init_script /etc/init.d/redisd
chkconfig redisd on
service redisd start|stop

1.5 redis关闭

  1. 第一种关闭方式

    断电,非正常关闭,容易导致数据丢失

    ps -ef | grep redis kill -9 PID

  2. 第二种关闭方式

    正常关闭,数据保存

    redis-cli shutdown # 关闭redis服务,通过客户端进行shutdown

    如果redis设置了密码,则需要先用客户端登录,然后再进行shutdown

    redis-cli -a password 127.0.0.1:6379> shutdown

    重新启动redis服务,使用客户端连接,会发现数据还在

三、持久化

Redis持久化,就是将内存中的数据,永久保存到磁盘上。

Redis持久化有两种方式:RDB(Redis DB)、AOF(AppendOnlyFile)

Redis 可以同时使用 AOF 持久化和 RDB 持久化。 在这种情况下, 当 Redis 重启时, 它会优先使用 AOF 文件来还原数据集, 因为 AOF 文件保存的数据集通常比 RDB 文件所保存的数据集更完整。

3.1 RDB(快照模式)

在默认情况下,Redis 将数据库快照保存在名字为dump.rdb的二进制文件中,可以在redis.conf配置文件中修改持久化信息。

save 900 1 表示在900秒内,至少更新了1条数据。Redis就将数据持久化到硬盘
save 300 10 表示在300内,至少更新了10条数据,Redis就会触发将数据持久化到硬盘
save 60 10000 表示60秒内,至少更新了10000条数据,Redis就会触发将数据持久化到硬盘

3.1.1 策略

  1. 自动:BGSAVE

按照配置文件中的条件满足就执行BGSAVE;

非阻塞,Redis服务正常接收处理客户端请求;

Redis会folk()一个新的子进程来创建RDB文件,子进程处理完后会向父进程发送一个信号,通知它处理完毕;

父进程用新的dump.rdb替代旧文件。

  1. 手动:SAVE

客户端(redis-cli)发起SAVE命令;

阻塞Redis服务,无法响应客户端请求;

创建新的dump.rdb替代旧文件。

3.1.2 优点

  • 执行效率高;

  • 恢复大数据集速度较AOF快。

3.1.3 缺点

  • 会丢失最近写入、修改的而未能持久化的数据;

  • folk过程非常耗时,会造成毫秒级不能响应客户端请求。

3.2 AOF(追加模式、文本重演)

AOF默认关闭,需要在配置文件中手动开启。

记录所有的写操作命令,在服务启动的时候使用这些命令就可以还原数据库。

Append only file,采用追加的方式保存,默认文件appendonly.aof。

3.2.1 写入机制

AOF机制,添加了一个内存缓冲区(buffer):

  1. 将内容写入缓冲区
  2. 当缓冲区被填满、或者用户手动执行fsync、或者系统根据指定的写入磁盘策略自动调用fdatasync命令,才将缓冲区里的内容真正写入磁盘里
  3. 在缓冲区里的内容未写入磁盘之前,可能会丢失

3.2.2 写入磁盘的策略

appendfsync选项,这个选项的值可以是always、everysec或者no

  • always:服务器每写入一个命令,就调用一次fdatasync,将缓冲区里面的命令写入到硬盘。这种模式下,服务器出现故障,也不会丢失任何已经成功执行的命令数据
  • everysec(默认):服务器每一秒重调用一次fdatasync,将缓冲区里面的命令写入到硬盘。这种模式下,服务器出现故障,最多只丢失一秒钟内的执行的命令数据
  • no:服务器不主动调用fdatasync,由操作系统决定何时将缓冲区里面的命令写入到硬盘。这种模式下,服务器遭遇意外停机时,丢失命令的数量是不确定的,no 选项并不能给服务器性能带来多大的提升,而且也会增加系统奔溃时数据丢失的数量。

运行速度:always的速度慢,everysec和no都很快

3.2.3 重写机制

AOF文件过大,合并重复的操作,AOF会使用尽可能少的命令来记录

  1. 重写过程

(1)folk一个子进程负责重写AOF文件

(2)子进程会创建一个临时文件写入AOF信息

(3)父进程会开辟一个内存缓冲区接收新的写命令

(4)子进程重写完成后,父进程会获得一个信号,将父进程接收到的新的写操作由子进程写入到临时文件中

(5)新文件替代旧文件

重写的本质:就是将操作同一个键的命令,合并。从而减小AOF文件的体积

  1. 重写触发机制

 (1)手动:

 客户端向服务器发送BGREWRITEAOF命令

 (2)自动:

 配置文件中的选项,自动执行BGREWRITEAOF命令

  • auto-aof-rewrite-min-size :触发AOF重写所需的最小体积:只要在AOF文件的体积大于等于size时,才会考虑是否需要进行AOF重写,这个选项用于避免对体积过小的AOF文件进行重写
  • auto-aof-rewrite-percentage :指定触发重写所需的AOF文件体积百分比:当AOF文件的体积大于auto-aof-rewrite-min-size指定的体积,并且超过上一次重写之后的AOF文件体积的percent %时,就会触发AOF重写。(如果服务器刚刚启动不久,还没有进行过AOF重写,那么使用服务器启动时载入的AOF文件的体积来作为基准值)。将这个值设置为0表示关闭自动AOF重写。
  1. 优点
  • 写入机制,默认fysnc(手工同步)每秒执行,性能很好不阻塞服务,最多丢失一秒的数据;

  • 重写机制,优化AOF文件;

  • 如果误操作了(FLUSHALL等),只要AOF未被重写,停止服务移除AOF文件尾部FLUSHALL命令,重启Redis,可以将数据集恢复到FLUSHALL 执行之前的状态。

  1. 缺点
  • 相同数据集,AOF文件体积较RDB大了很多;

  • 恢复数据库速度较RDB慢(文本,命令重演)

四、集群

4.1 redis集群简介

4.1.1 集群的概念

  所谓的集群,就是通过添加服务器的数量,提供相同的服务,从而让服务器达到一个稳定、高效的状态。

4.1.1.1 使用redis集群的必要性

  问题:我们已经部署好了redis,并且能启动一个redis,实现数据的读写,为什么还要学习redis集群?

  答:(1)单个redis存在不稳定性。当redis服务宕机了,就没有可用的服务了。

    (2)单个redis的读写能力是有限的。

  总结:redis集群是为了强化redis的读写能力。

4.1.1.2 如何学习redis集群

说明:(1)redis集群中,每一个redis称之为一个节点。

    (2)redis集群中,有两种类型的节点:主节点(master)、从节点(slave)。

    (3)redis集群,是基于redis主从复制实现。

所以,学习redis集群,就是从学习redis主从复制模型开始的。

4. 2 redis主从复制

4.2.1 概念

  主从复制模型中,有多个redis节点。

  其中,有且仅有一个为主节点Master。从节点Slave可以有多个。

  只要网络连接正常,Master会一直将自己的数据更新同步给Slaves,保持主从同步。

4.2.2 特点

  (1)主节点Master可读、可写.

  (2)从节点Slave只读。(read-only)

  因此,主从模型可以提高读的能力,在一定程度上缓解了写的能力。因为能写仍然只有Master节点一个,可以将读的操作全部移交到从节点上,变相提高了写能力。

4.2.3 基于配置实现

  1. 需求
  • 主节点:6380
  • 从节点:6381、6382
  1. 配置步骤

(1)在/usr/local目录下,创建一个/redis/master-slave目录

mkdir -p /usr/local/redis/master-slave

(2)在master-slave目录下,创建三个子目录6380、6381、6382

mkdir 6380 6381 6382

(3)依次拷贝redis解压目录下的redis.conf配置文件,到这三个子目录中

cp /usr/local/src/redis-5.0.4/redis.conf 6380/
cp /usr/local/src/redis-5.0.4/redis.conf 6381/
cp /usr/local/src/redis-5.0.4/redis.conf 6382/

(4)进入6380目录,修改redis.conf,将port端口修改成6380即可

(5)进入6381目录,修改redis.conf,将port端口改成6381,同时指定开启主从复制

#     主节点ip 主节点端口
replicaof 127.0.0.1 6380

(6)进入6382目录,修改redis.conf,将port端口改成6382,同时指定开启主从复制

  1. 测试

(1)打开三个shell窗口,在每一个窗口中,启动一个redis节点。查看日志输出。(不要改成后台模式启动,看不到日志,不直观)

(2)另外再打开三个shell窗口,在每一个窗口中,登陆一个redis节点

(3)在主节点6380上,进行读写操作,操作成功

(4)在从节点6381上,读操作执行成功,并且成功从6380上同步了数据;写操作执行失败。(从节点,只能读,不能写)

# 写操作执行失败提示
(error) READONLY You can't write against a read only replica.

4.3 Sentinel哨兵模式

4.3.1 主从模式的缺陷

当主节点宕机了,整个集群就没有可写的节点了。

问:由于从节点上备份了主节点的所有数据,那在主节点宕机的情况下,如果能够将从节点变成一个主节点,是不是就可以解决这个问题了呢?

答:是的,这个就是Sentinel哨兵的作用。

4.3.2 哨兵的任务

Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance), 该系统执行以下三个任务:

  1. 监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。

  2. 提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。

  3. 自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作, 它会进行选举,将其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。

4.3.2.1 监控(Monitoring)

  (1)Sentinel可以监控任意多个Master和该Master下的Slaves。(即多个主从模式)

  (2)同一个哨兵下的、不同主从模型,彼此之间相互独立。

  (3)Sentinel会不断检查Master和Slaves是否正常。

4.3.2.1 自动故障切换(Automatic failover)

监控同一个Master的Sentinel会自动连接,组成一个分布式的Sentinel网络,互相通信并交换彼此关于被监视服务器的信息。

疑问:为什么要使用sentinel网络呢?

答:当只有一个sentinel的时候,如果这个sentinel挂掉了,那么就无法实现自动故障切换了。

  在sentinel网络中,只要还有一个sentinel活着,就可以实现故障切换。

4.3.2.2 故障切换的过程

(1)投票(半数原则)

  当任何一个Sentinel发现被监控的Master下线时,会通知其它的Sentinel开会,投票确定该Master是否下线(半数以上,所以sentinel通常配奇数个)。

(2)选举

  当Sentinel确定Master下线后,会在所有的Slaves中,选举一个新的节点,升级成Master节点。

  其它Slaves节点,转为该节点的从节点。

(3)原Master重新上线

  当原Master节点重新上线后,自动转为当前Master节点的从节点。

4.3.3 哨兵模式部署

4.3.3.1 需求

前提:已经存在一个正在运行的主从模式。

另外,配置三个Sentinel实例,监控同一个Master节点

4.3.3.2 配置Sentinel

(1)在/usr/local目录下,创建/redis/sentinels/目录

cd /usr/local/redis
mkdir sentinels

(2)在sentinels目录下,依次创建s1、s2、s3三个子目录中

cd sentinels
mkdir s1 s2 s3

(3)依次拷贝redis解压目录下的sentinel.conf文件,到这三个子目录中

cp /usr/local/src/redis-5.0.4/sentinel.conf s1/
cp /usr/local/src/redis-5.0.4/sentinel.conf s2/
cp /usr/local/src/redis-5.0.4/sentinel.conf s3/

(4)依次修改s1、s2、s3子目录中的sentinel.conf文件,修改端口,并指定要监控的主节点。(从节点不需要指定,sentinel会自动识别)

# s1 哨兵配置
port 26379
sentinel monitor mymaster 127.0.0.1 6380 2 

# mymaster为主节点别名,127.0.0.1为主节点IP,6380为主节点端口,2为触发故障切换的最少哨兵数量

# s2 哨兵配置
port 26380
sentinel monitor mymaster 127.0.0.1 6380 2

# s3 哨兵配置
port 26381
sentinel monitor mymaster 127.0.0.1 6380 2

(5)再打开三个shell窗口,在每一个窗口中,启动一个哨兵实例,并观察日志输出


进入redis的安装目录,/usr/local/bin/,也可以不用进,因为前面的那个目录在环境变量中。

对于用redis-server启动哨兵的方式如下:

核心日志输出:

4.3.4 测试

(1)先关闭6380节点(kill掉)。发现,确实重新指定了一个主节点

(2)再次上线6380节点。发现,6380节点成为了新的主节点的从节点。

4.3.5 结论

  Sentinel哨兵模式,确实能实现自动故障切换。提供稳定的服务。

4.3.6 注意事项

如果哨兵和redis节点不在同一台服务器上,注意IP绑定的问题。

(1)主从模型,所有的节点,使用ip绑定

(2)所有的哨兵,也都使用ip去绑定主机

(3)所有的哨兵,都是通过主节点的ip,去监控主从模型

五、 Redis-cluster集群

5.1 哨兵模式的缺陷

在哨兵模式中,仍然只有一个Master节点。当并发写请求较大时,哨兵模式并不能缓解写压力。

我们知道只有主节点才具有写能力,那如果在一个集群中,能够配置多个主节点,是不是就可以缓解写压力了呢?

答:是的。这个就是redis-cluster集群模式。

5.2 Redis-cluster集群概念

(1)由多个Redis服务器组成的分布式网络服务集群;

(2)集群之中有多个Master主节点,每一个主节点都可读可写;

(3)节点之间会互相通信,两两相连;

(4)Redis集群无中心节点。

5.3 集群节点复制

在Redis-Cluster集群中,可以给每一个主节点添加从节点,主节点和从节点直接遵循主从模型的特性。

当用户需要处理更多读请求的时候,添加从节点可以扩展系统的读性能。

5.4 故障转移

Redis集群的主节点内置了类似Redis Sentinel的节点故障检测和自动故障转移功能,当集群中的某个主节点下线时,集群中的其他在线主节点会注意到这一点,并对已下线的主节点进行故障转移。

集群进行故障转移的方法和Redis Sentinel进行故障转移的方法基本一样,不同的是,在集群里面,故障转移是由集群中其他在线的主节点负责进行的,所以集群不必另外使用Redis Sentinel。

5.5 集群分片策略

Redis-cluster分片策略,是用来解决key存储位置的。

集群将整个数据库分为16384个槽位slot,所有key-value数据都存储在这些slot中的某一个上。一个slot槽位可以存放多个数据,key的槽位计算公式为:slot_number=crc16(key)%16384,其中crc16为16位的循环冗余校验和函数。

集群中的每个主节点都可以处理0个至16383个槽,当16384个槽都有某个节点在负责处理时,集群进入上线状态,并开始处理客户端发送的数据命令请求。

5.6 集群redirect转向

由于Redis集群无中心节点,请求会随机发给任意主节点;

主节点只会处理自己负责槽位的命令请求,其它槽位的命令请求,该主节点会返回客户端一个转向错误;

客户端根据错误中包含的地址和端口重新向正确的负责的主节点发起命令请求。

5.7 集群搭建

5.7.1 准备工作

redis5.0版本之后可以直接使用redis-cli命令创建集群,不使用redis-trib.rb命令了。

5.7.2 集群规划

(1)Redis集群最少需要6个节点,3主3从,可以分布在一台或者多台主机上。

真集群:6台主机,每台主机的redis服务使用的IP不同,端口号随意,一样不一样都可以

假集群,一台主机,redis服务使用的IP相同,端口号不同

本例子是在一台主机上创建假集群,不同的端口表示不同的redis节点,如下:

主节点: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 127.0.0.1:7006

后期新加的主节点:127.0.0.1:7007

后期新家的从节点:127.0.0.1:7008

(2)在/usr/local/src/redis-5.0.4/下创建cluster目录,其下创建7001、7002…7006目录,如下:

(3)将redis解压路径下的配置文件redis.conf,依次拷贝到每个700X目录内,并修改每个700X目录下的redis.conf配置文件:

# cd /usr/local/src/redis-5.0.4/cluster
# mkdir {7001,7002,7003,7004,7005,7006}
# mkdir -p /var/log/redis/{7001,7002,7003,7004,7005,7006}

# redis.conf文件示例
bind 127.0.0.1
port 7001
daemonize yes
pidfile /var/run/redis_7001.pid
dir "./" # node.conf文件保存路径
logfile "/var/log/redis/7001/redis.log"
appendonly yes
appendfsync always
cluster-enabled yes
cluster-config-file nodes-7001.conf # 该文件中包含集群信息

# 其他配置文件类似,把端口号修改一下就行了

5.7.3 启动每个节点redis服务

批量启动脚本:

# vim s/usr/local/src/redis-5.0.4/cluster/ctart_cluster.sh
#!/bin/bash

cd ./7001 && /usr/local/src/redis-5.0.4/src/redis-server ./redis.conf
cd ../7002 && /usr/local/src/redis-5.0.4/src/redis-server ./redis.conf
cd ../7003 && /usr/local/src/redis-5.0.4/src/redis-server ./redis.conf
cd ../7004 && /usr/local/src/redis-5.0.4/src/redis-server ./redis.conf
cd ../7005 && /usr/local/src/redis-5.0.4/src/redis-server ./redis.conf
cd ../7006 && /usr/local/src/redis-5.0.4/src/redis-server ./redis.conf
cd ..

# chmod +x start_cluster.sh

注意:一定要进入700X目录中启动,因为它会自动在当前目录中创建cluster-config,即nodes.conf。因为你在哪个目录下执行这个命令,则node.conf文件就会在该目录下创建。

但是若是在配置文件中配置dir为其他目录,则该文件会创建在dir指定目录下

或者把redis-server程序文件依次拷贝到每个700x目录下,然后使用不同目录的redis-server程序文件启动

关闭脚本:

# vim /usr/local/src/redis-5.0.4/cluster/shutdown_cluster.sh
#!/bin/bash

pgrep redis-server | xargs -exec kill -9

# chmod +x shutdown_cluster.sh

执行启动脚本批量启动:

# ./start_cluster.sh

5.7.4 执行创建集群命令

进入到redis源码存放目录/usr/local/src/redis-5.0.4/src下,把redis-cli文件拷贝到/usr/local/bin/目录下

cd  /usr/local/src/redis-5.0.4/cluster
/usr/local/src/redis-5.0.4/src/redis-cli --cluster create 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 127.0.0.1:7006 --cluster-replicas 1 

# --cluster-replicas 1  表示主从配置比,1表示的是1:1,前三个是主,后三个是从
# 若配置文件中设置的密码,则还需要加上-a passwod

......
Can I set the above configuration? (type 'yes' to accept): yes
......
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

5.7.5 查询集群信息

注意:查询集群信息需要加上-c参数

或者直接执行命令查询,如下面所示;或者登陆到其中一个集群节点,使用命令cluster nodes进行查询

# /usr/local/src/redis-5.0.4/src/redis-cli -c -h 127.0.0.1 -p 7001 cluster nodes
7d388cc31df969d3e1715ce9644318bfd48317b1 127.0.0.1:7004@17004 slave 59b6597448b668a355d85dcc7a0623bc36263e5f 0 1564918712465 4 connected
bbe8b7035bfd31c47bec7d612acc112cd2869368 127.0.0.1:7003@17003 master - 0 1564918714483 3 connected 10923-16383
456921ae96af71d8183101f798cf5ceda4b0381e 127.0.0.1:7005@17005 slave bbe8b7035bfd31c47bec7d612acc112cd2869368 0 1564918713000 5 connected
5612ffbb0407dbda50828b505a16b39ede51168b 127.0.0.1:7006@17006 slave 4dad696ede24995a57c5fd790faa95c72c187a22 0 1564918713474 6 connected
4dad696ede24995a57c5fd790faa95c72c187a22 127.0.0.1:7001@17001 myself,master - 0 1564918713000 1 connected 0-5460
59b6597448b668a355d85dcc7a0623bc36263e5f 127.0.0.1:7002@17002 master - 0 1564918712000 2 connected 5461-10922

参数说明:

  • -c:表示以集群方式连接惹redis
  • -h:指定IP地址
  • -p:指定端口
  • cluster nodes:查询集群节点信息
  • cluster info:查询集群状态信息

其他查询方法:

# /usr/local/src/redis-5.0.4/src/redis-cli --cluster check 127.0.0.1:7001
127.0.0.1:7001 (4dad696e...) -> 0 keys | 5461 slots | 1 slaves.
127.0.0.1:7003 (bbe8b703...) -> 0 keys | 5461 slots | 1 slaves.
127.0.0.1:7002 (59b65974...) -> 0 keys | 5462 slots | 1 slaves.
[OK] 0 keys in 3 masters.
0.00 keys per slot on average.
>>> Performing Cluster Check (using node 127.0.0.1:7001)
M: 4dad696ede24995a57c5fd790faa95c72c187a22 127.0.0.1:7001
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: 7d388cc31df969d3e1715ce9644318bfd48317b1 127.0.0.1:7004
   slots: (0 slots) slave
   replicates 59b6597448b668a355d85dcc7a0623bc36263e5f
M: bbe8b7035bfd31c47bec7d612acc112cd2869368 127.0.0.1:7003
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: 456921ae96af71d8183101f798cf5ceda4b0381e 127.0.0.1:7005
   slots: (0 slots) slave
   replicates bbe8b7035bfd31c47bec7d612acc112cd2869368
S: 5612ffbb0407dbda50828b505a16b39ede51168b 127.0.0.1:7006
   slots: (0 slots) slave
   replicates 4dad696ede24995a57c5fd790faa95c72c187a22
M: 59b6597448b668a355d85dcc7a0623bc36263e5f 127.0.0.1:7002
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

# /usr/local/src/redis-5.0.4/src/redis-cli --cluster info 127.0.0.1:7001 
127.0.0.1:7001 (4dad696e...) -> 0 keys | 5461 slots | 1 slaves.
127.0.0.1:7003 (bbe8b703...) -> 0 keys | 5461 slots | 1 slaves.
127.0.0.1:7002 (59b65974...) -> 0 keys | 5462 slots | 1 slaves.
[OK] 0 keys in 3 masters.
0.00 keys per slot on average.

5.7.6 redis cluster集群重新启动

因为集群已经创建过了,若是关机等原因关闭了redis服务,则只需要执行批量启动脚本即可,就会自动开启集群,因为有node.conf文件的存在

5.7.7 redis-cli集群命令帮助

# /usr/local/src/redis-5.0.4/src/redis-cli --cluster help
Cluster Manager Commands:
  create         host1:port1 ... hostN:portN
                 --cluster-replicas <arg>
  check          host:port
                 --cluster-search-multiple-owners
  info           host:port
  fix            host:port
                 --cluster-search-multiple-owners
  reshard        host:port
                 --cluster-from <arg>
                 --cluster-to <arg>
                 --cluster-slots <arg>
                 --cluster-yes
                 --cluster-timeout <arg>
                 --cluster-pipeline <arg>
                 --cluster-replace
  rebalance      host:port
                 --cluster-weight <node1=w1...nodeN=wN>
                 --cluster-use-empty-masters
                 --cluster-timeout <arg>
                 --cluster-simulate
                 --cluster-pipeline <arg>
                 --cluster-threshold <arg>
                 --cluster-replace
  add-node       new_host:new_port existing_host:existing_port
                 --cluster-slave
                 --cluster-master-id <arg>
  del-node       host:port node_id
  call           host:port command arg arg .. arg
  set-timeout    host:port milliseconds
  import         host:port
                 --cluster-from <arg>
                 --cluster-copy
                 --cluster-replace
  help           

For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster.

5.8 集群管理

5.8.1 添加新主节点

redis-cli --cluster add-node new_host:new_port existing_host:existing_port --cluster-master-id node_id

5.8.2 hash槽重新分配

添加完新节点后,需要对新添加的主节点进行hash槽重新分配,这样该主节点才能存储数据,redis共有16384个槽。

redis-cli --cluster reshard host:port --cluster-from node_id --cluster-to node_id --cluster-slots <args> --cluster-yes

5.8.2 添加新从节点

redis-cli --cluster add-node new_host:new_port existing_host:existing_port --cluster-slave --cluster-master-id node_id

5.8.3 删除节点

redis-cli --cluster  del-node host:port node_id

5.8.4 集群常用命令

# 创建集群
redis-cli --cluster create host1:port1 ... hostN:portN --cluster-replicas <arg>
# 例子
redis-cli --cluster create 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 127.0.0.1:7006 --cluster-replicas 1
# 例子说明
host1:port1 ... hostN:portN表示的是要添加的集群的节点IP和端口,
--cluster-replicas <arg>表示的是主从节点比例,参数1表示前三个是主节点,后三个是从节点
也就是说7001,7002,7003端口对应的节点是主节点,7004,7005,7006对应的节点是从节点

# 查询集群节点信息
redis-cli -c -p 7001 cluster nodes        
7d388cc31df969d3e1715ce9644318bfd48317b1 127.0.0.1:7004@17004 slave 59b6597448b668a355d85dcc7a0623bc36263e5f 0 1564923261350 4 connected
bbe8b7035bfd31c47bec7d612acc112cd2869368 127.0.0.1:7003@17003 master - 0 1564923263366 3 connected 10923-16383
456921ae96af71d8183101f798cf5ceda4b0381e 127.0.0.1:7005@17005 slave bbe8b7035bfd31c47bec7d612acc112cd2869368 0 1564923262000 5 connected
5612ffbb0407dbda50828b505a16b39ede51168b 127.0.0.1:7006@17006 slave 4dad696ede24995a57c5fd790faa95c72c187a22 0 1564923260000 6 connected
4dad696ede24995a57c5fd790faa95c72c187a22 127.0.0.1:7001@17001 myself,master - 0 1564923263000 1 connected 0-5460
59b6597448b668a355d85dcc7a0623bc36263e5f 127.0.0.1:7002@17002 master - 0 1564923262358 2 connected 5461-10922

# 说明:以下的操作均是以上面这个为参数示例

# 给集群添加一个新主节点
redis-cli --cluster add-node new_host:new_port existing_host:existing_port --cluster-master-id node_id
# 例子
redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7003 --cluster-master-id bbe8b7035bfd31c47bec7d612acc112cd2869368
# 例子说明
new_host:new_port为要新添加的主节点IP和端口,此处是127.0.0.1:7007
existing_host:existing_port表示的是已存在的最后一个主节点的IP和端口,这个可以从上述的节点信息中查看到,根据slots槽数,7003端口对应的节点槽数是10923-16383,16383表示的是最后的槽数
--cluster-master-id表示的是最后一个主节点的节点id,表示的是新添加的主节点要在这个节点后面

# 再次查看集群信息
redis-cli -c -p 7001 cluster nodes        
7d388cc31df969d3e1715ce9644318bfd48317b1 127.0.0.1:7004@17004 slave 59b6597448b668a355d85dcc7a0623bc36263e5f 0 1564923261350 4 connected
bbe8b7035bfd31c47bec7d612acc112cd2869368 127.0.0.1:7003@17003 master - 0 1564923263366 3 connected 10923-16383
7020c8df9423686727783c60bd2f0e367634ba84 127.0.0.1:7007@17007 master - 0 1564923260344 0 connected
456921ae96af71d8183101f798cf5ceda4b0381e 127.0.0.1:7005@17005 slave bbe8b7035bfd31c47bec7d612acc112cd2869368 0 1564923262000 5 connected
5612ffbb0407dbda50828b505a16b39ede51168b 127.0.0.1:7006@17006 slave 4dad696ede24995a57c5fd790faa95c72c187a22 0 1564923260000 6 connected
4dad696ede24995a57c5fd790faa95c72c187a22 127.0.0.1:7001@17001 myself,master - 0 1564923263000 1 connected 0-5460
59b6597448b668a355d85dcc7a0623bc36263e5f 127.0.0.1:7002@17002 master - 0 1564923262358 2 connected 5461-10922
# 会发现7007端口对应的节点已经加入到集群中,是主节点,但是没有从节点,也没有分配槽数

# 给新添加的主节点分配slots槽数
redis-cli --cluster reshard host:port --cluster-from node_id --cluster-to node_id --cluster-slots 500 --cluster-yes
# 例子
redis-cli --cluster reshard 127.0.0.1:7007 --cluster-from 4dad696ede24995a57c5fd790faa95c72c187a22 --cluster-to 7020c8df9423686727783c60bd2f0e367634ba84 --cluster-slots 500 
# 例子说明
host:port表示的是新添加的那个主节点IP和端口,此处表示的是127.0.0.1:7007
--cluster-from node_id表示的是集群第一个主节点的节点id,这个可以现有集群的slots槽数分配看出,此处表示的是7001端口对应的节点
--cluster-to node_id表示的是集群最后一个主节点的节点id,也就是新添加的那个主节点id,此处表示的是7007端口对应的节点
--cluster-slots 500表示的是给新主节点分配多少,此处500表示是分配从0-499个slots槽数,若不加上这个会让手动输入
--cluster-yes表示的是自动应答为yes,若不加上这个会让手动输入yes,表示同意此次分配

# 再次查看集群信息
/redis-cli -c -p 7001 cluster nodes                                         7d388cc31df969d3e1715ce9644318bfd48317b1 127.0.0.1:7004@17004 slave 59b6597448b668a355d85dcc7a0623bc36263e5f 0 1564924042000 4 connected
bbe8b7035bfd31c47bec7d612acc112cd2869368 127.0.0.1:7003@17003 master - 0 1564924042157 3 connected 10923-16383
7020c8df9423686727783c60bd2f0e367634ba84 127.0.0.1:7007@17007 master - 0 1564924040140 7 connected 0-499
456921ae96af71d8183101f798cf5ceda4b0381e 127.0.0.1:7005@17005 slave bbe8b7035bfd31c47bec7d612acc112cd2869368 0 1564924040000 5 connected
5612ffbb0407dbda50828b505a16b39ede51168b 127.0.0.1:7006@17006 slave 4dad696ede24995a57c5fd790faa95c72c187a22 0 1564924041149 6 connected
4dad696ede24995a57c5fd790faa95c72c187a22 127.0.0.1:7001@17001 myself,master - 0 1564924040000 1 connected 500-5460
59b6597448b668a355d85dcc7a0623bc36263e5f 127.0.0.1:7002@17002 master - 0 1564924043166 2 connected 5461-10922
# 会发现7007端口对应的主节点已经有slots槽数了,并且是从0开始的

# 给集群中某个主节点再添加一个从节点
redis-cli --cluster add-node new_host:new_port existing_host:existing_port --cluster-slave --cluster-master-id node_id
# 例子
redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7008 --cluster-slave --cluster-master-id 7020c8df9423686727783c60bd2f0e367634ba84
# 例子说明
new_host:new_port表示的是要添加的那个从节点的IP和端口,此处表示的是127.0.0.1:7008
existing_host:existing_port表示的是要给哪个主节点添加从节点,此处表示的是127.0.0.1:7007
--cluster-slave表示的是要添加从节点,否则则是添加主节点了
--cluster-master-id node_id表示要给哪个主节点添加从节点的该主节点节点id

# 再次查看集群信息
redis-cli -c -p 7001 cluster nodes                                         7020c8df9423686727783c60bd2f0e367634ba84 127.0.0.1:7007@17007 master - 0 1564924845000 7 connected 0-499
4dad696ede24995a57c5fd790faa95c72c187a22 127.0.0.1:7001@17001 myself,master - 0 1564924843000 1 connected 500-5460
5612ffbb0407dbda50828b505a16b39ede51168b 127.0.0.1:7006@17006 slave 4dad696ede24995a57c5fd790faa95c72c187a22 0 1564924845214 6 connected
7d388cc31df969d3e1715ce9644318bfd48317b1 127.0.0.1:7004@17004 slave 59b6597448b668a355d85dcc7a0623bc36263e5f 0 1564924843195 4 connected
bbe8b7035bfd31c47bec7d612acc112cd2869368 127.0.0.1:7003@17003 master - 0 1564924844205 3 connected 10923-16383
456921ae96af71d8183101f798cf5ceda4b0381e 127.0.0.1:7005@17005 slave bbe8b7035bfd31c47bec7d612acc112cd2869368 0 1564924845000 5 connected
415db07121ba946b202bca98e15cbdffc60bc18a 127.0.0.1:7008@17008 slave 7020c8df9423686727783c60bd2f0e367634ba84 0 1564924846224 7 connected
c3e04f0e8710c25d59703374a224ee8bec776e43 :0@0 master,fail,noaddr - 1564924804548 1564924802833 0 disconnected
59b6597448b668a355d85dcc7a0623bc36263e5f 127.0.0.1:7002@17002 master - 0 1564924844000 2 connected 5461-10922
# 会发现7008端口对应的节点已经是7007端口对应的从节点

# 从集群中删除一个从节点
redis-cli --cluster  del-node host:port node_id
# 例子
redis-cli --cluster del-node 127.0.0.1:7008 415db07121ba946b202bca98e15cbdffc60bc18a
# 例子说明
host:port表示的是要删除的那个节点的IP和端口,此处是127.0.0.1:7008
node_id表示的是删除的那个节点的节点id

# 其他命令有待补充

5.9 注意事项

5.9.1 防火墙端口放行

若是允许Redis集群被外网用户访问,除了需要修改配置文件外,还需要修改防火墙,开放集群中reids节点的端口。

说明:如果要开放一个范围的端口,可以使用冒号来分割,即: 7001:7004,表示开放7001-7004之间所有的端口

5.9.2 登录节点问题

若是登录的是集群中的节点,需要加上-c参数;否则不用加该参数

# 登录集群节点的命令
redis-cli -c -h ip -p port -a password

# 登录一般节点或者从节点的命令
redis-cli -h ip -p port -a password

5.9.3 如何删除集群中无效的节点

redis-cli -c -p 7001 cluster nodes                                        
7020c8df9423686727783c60bd2f0e367634ba84 127.0.0.1:7007@17007 master - 0 1564925352648 7 connected 0-499
4dad696ede24995a57c5fd790faa95c72c187a22 127.0.0.1:7001@17001 myself,master - 0 1564925349000 1 connected 500-5460
5612ffbb0407dbda50828b505a16b39ede51168b 127.0.0.1:7006@17006 slave 4dad696ede24995a57c5fd790faa95c72c187a22 0 1564925351000 6 connected
7d388cc31df969d3e1715ce9644318bfd48317b1 127.0.0.1:7004@17004 slave 59b6597448b668a355d85dcc7a0623bc36263e5f 0 1564925354665 4 connected
bbe8b7035bfd31c47bec7d612acc112cd2869368 127.0.0.1:7003@17003 master - 0 1564925353657 3 connected 10923-16383
456921ae96af71d8183101f798cf5ceda4b0381e 127.0.0.1:7005@17005 slave bbe8b7035bfd31c47bec7d612acc112cd2869368 0 1564925349000 5 connected
c3e04f0e8710c25d59703374a224ee8bec776e43 :0@0 master,fail,noaddr - 1564924804548 1564924802833 0 disconnected
59b6597448b668a355d85dcc7a0623bc36263e5f 127.0.0.1:7002@17002 master - 0 1564925352000 2 connected 5461-10922

# 如上集群中有一个无效的节点信息,要如何删除,这个还不知道咋操作。
点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
2年前
Java获得今日零时零分零秒的时间(Date型)
publicDatezeroTime()throwsParseException{    DatetimenewDate();    SimpleDateFormatsimpnewSimpleDateFormat("yyyyMMdd00:00:00");    SimpleDateFormatsimp2newS
Stella981 Stella981
2年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
2年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这