Redis笔记

Redis

介绍

Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库。
Redis 与其他 key - value 缓存产品有以下三个特点:

Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
Redis支持数据的备份,即master-slave模式的数据备份。

优势

  1. 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
  2. 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
  3. 原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTIEXEC指令包起来。
  4. 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。

对比

Redis有着更为复杂的数据结构并且提供对他们的原子性操作,这是一个不同于其他数据库的进化路径。Redis的数据类型都是基于基本数据结构的同时对程序员透明,无需进行额外的抽象。
Redis运行在内存中但是可以持久化到磁盘,所以在对不同数据集进行高速读写时需要权衡内存,因为数据量不能大于硬件内存。在内存数据库方面的另一个优点是,相比在磁盘上相同的复杂的数据结构,在内存中操作起来非常简单,这样Redis可以做很多内部复杂性很强的事情。同时,在磁盘格式方面他们是紧凑的以追加的方式产生的,因为他们并不需要进行随机访问。

安装

以下操作使用系统:

CentOS Linux release 7.6.1810 (Core) 
Linux demo1 3.10.0-957.21.3.el7.x86_64 #1 SMP Tue Jun 18 16:35:19 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

安装配置

yum -y install gcc gcc-c++
wget http://download.redis.io/releases/redis-6.0.6.tar.gz
tar xf redis-6.0.6.tar.gz -C /usr/local/
cd /usr/local/redis-6.0.6/
make

安装若报错如下:
报错截图
查看gcc的版本是否小于5.

[root@demo1 redis-6.0.6]# gcc -v
使用内建 specs。
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/lto-wrapper
目标:x86_64-redhat-linux
配置为:../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux
线程模型:posix
gcc 版本 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC)

需安装更高版本的gcc

yum -y install centos-release-scl
yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
scl enable devtoolset-9 bash
echo "source /opt/rh/devtoolset-9/enable" >> /etc/profile

查看下gcc版本是否为9.x gcc version 9.3.1 20200408 (Red Hat 9.3.1-2) (GCC)
更新版本后再次make即可

启动

[root@demo1 redis-6.0.6]# ./src/redis-server 
29548:C 28 Jul 2020 15:37:48.562 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
29548:C 28 Jul 2020 15:37:48.562 # Redis version=6.0.6, bits=64, commit=00000000, modified=0, pid=29548, just started
29548:C 28 Jul 2020 15:37:48.562 # Warning: no config file specified, using the default config. In order to specify a config file use ./src/redis-server /path/to/redis.conf
29548:M 28 Jul 2020 15:37:48.563 * Increased maximum number of open files to 10032 (it was originally set to 1024).
                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 6.0.6 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                   
 (    '      ,       .-`  | `,    )     Running in standalone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 29548
  `-._    `-._  `-./  _.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |           http://redis.io        
  `-._    `-._`-.__.-'_.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'                                               

配置

[root@demo1 ~]# ln -s /usr/local/redis-6.0.6/src/* /usr/bin/
[root@demo1 ~]# vim /usr/local/redis-6.0.6/redis.conf 
 ···
 222 daemonize yes
 ···
  • 启动方式
[root@demo1 ~]# redis-server /usr/local/redis-6.0.6/redis.conf 
29579:C 28 Jul 2020 15:53:01.359 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
29579:C 28 Jul 2020 15:53:01.359 # Redis version=6.0.6, bits=64, commit=00000000, modified=0, pid=29579, just started
29579:C 28 Jul 2020 15:53:01.359 # Configuration loaded
[root@demo1 ~]# ps -ef | grep redis | grep -v grep
root      29580      1  0 15:53 ?        00:00:00 redis-server 127.0.0.1:6379
[root@demo1 ~]# netstat -anpt | grep redis | grep -v grep
tcp        0      0 127.0.0.1:6379          0.0.0.0:*               LISTEN      29580/redis-server

关闭

kill 29580

启停脚本

#!/bin/bash
#owner:WCY
if [ $# -ne 2 ]; then
        echo "usage: $0 port"
        exit -1;
fi
PORT=$1
REDIS_SERVER="/usr/bin/redis-server"
REDIS_CLI="/usr/bin/redis-cli"
#REDIS_CONF="/usr/local/redis-6.0.6/redis_$PORT.conf"
REDIS_CONF="/usr/local/redis-6.0.6/redis.conf"
###################################################################
cmd="ps -ef | grep ${REDIS_SERVER} | grep -Ev 'grep|vim|defunct' | grep '$PORT' | awk '{ print \$2 }'"
PID=$(eval ${cmd})

START(){
if [ ! -e $REDIS_SERVER ]; then
        echo "$REDIS_SERVER does not exist!"
        exit -1
fi
if [ ! -e $REDIS_CONF ]; then
        echo "$REDIS_CONF does not exist!"
        exit -1
fi
if [[ $PID"e" != "e" ]]; then
        echo "redis-server(port:$PORT) is running, can't start"
        exit -1
else
        $REDIS_SERVER $REDIS_CONF &
fi
startfail=1
for i in `seq 0 180`
do
        PID=$(eval ${cmd})
        #echo $PID
        if [ $PID"e" != "e" ]; then
                ${REDIS_SERVER} --version
                echo "Redis server(port:$PORT) is stared..."
                startfail=0
                break
        fi
        sleep 1
done
exit $startfail
}
STOP(){
if [ ${PID}"e" = "e" ]; then
        echo "redis-server(port:$PORT) is not started"
        #exit -1
else
        kill $PID
fi
stopfail=1
for i in `seq 0 30`
do
        PID=$(eval ${cmd})
        #echo $PID
        if [ ${PID}"e" != "e" ]; then
                echo "redis-server(port:$PORT) is still running, waiting to stop[${i}]..."
        else
                echo "redis-server(port:$PORT) is stoped"
                stopfail=0
           break
        fi
        sleep 1
done
#exit $stopfail
}
case $2 in
start)
    START
;;
stop)
    STOP
;;
restart)
    STOP
    START
;;
*)
    echo "bash redis_service.sh PORT (start|stop|restart)"
;;
esac

配置文件详解

基本配置

protected-mode yes # 保护模式默认开启
port 6379  # 监听端口号,默认为 6379,如果你设为 0 ,redis 将不在 socket 上监听任何客户端连接。
daemonize no #是否以后台进程启动
databases 16 #创建database的数量(默认选中的是database 0)
save 900 1 #刷新快照到硬盘中,必须满足两者要求才会触发,即900秒之后至少1个关键字发生变化。
save 300 10 #必须是300秒之后至少10个关键字发生变化。
save 60 10000 #必须是60秒之后至少10000个关键字发生变化。
stop-writes-on-bgsave-error yes #后台存储错误停止写。
rdbcompression yes #使用LZF压缩rdb文件。
rdbchecksum yes #存储和加载rdb文件时校验。
dbfilename dump.rdb #设置rdb文件名。
dir ./ #设置工作目录,rdb文件会写入该目录。

主从配置

slaveof <masterip> <masterport> 设为某台机器的从服务器
masterauth <master-password> 连接主服务器的密码
slave-serve-stale-data yes # 当主从断开或正在复制中,从服务器是否应答
slave-read-only yes #从服务器只读
repl-ping-slave-period 10 #从ping主的时间间隔,秒为单位
repl-timeout 60 #主从超时时间(超时认为断线了),要比period大
slave-priority 100 #如果master不能再正常工作,那么会在多个slave中,选择优先值最小的一个slave提升为master,优先值为0表示不能提升为master。
repl-disable-tcp-nodelay no #主端是否合并数据,大块发送给slave
slave-priority 100 从服务器的优先级,当主服挂了,会自动挑slave priority最小的为主服

安全

requirepass foobared # 需要密码
rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52 #如果公共环境,可以重命名部分敏感命令 如config

限制

maxclients 10000 #最大连接数
maxmemory <bytes> #最大使用内存
maxmemory-policy volatile-lru #内存到极限后的处理
volatile-lru -> LRU算法删除过期key
allkeys-lru -> LRU算法删除key(不区分过不过期)
volatile-random -> 随机删除过期key
allkeys-random -> 随机删除key(不区分过不过期)
volatile-ttl -> 删除快过期的key
noeviction -> 不删除,返回错误信息
#解释 LRU ttl都是近似算法,可以选N个,再比较最适宜T踢出的数据
maxmemory-samples 3

日志模式

appendonly no #是否仅要日志
appendfsync no # 系统缓冲,统一写,速度快
appendfsync always # 系统不缓冲,直接写,慢,丢失数据少
appendfsync everysec #折衷,每秒写1次
no-appendfsync-on-rewrite no #为yes,则其他线程的数据放内存里,合并写入(速度快,容易丢失的多)
auto-AOF-rewrite-percentage 100 当前aof文件是上次重写是大N%时重写
auto-AOF-rewrite-min-size 64mb aof重写至少要达到的大小

慢查询

slowlog-log-slower-than 10000 #记录响应时间大于10000微秒的慢查询
slowlog-max-len 128 # 最多记录128条

服务端命令

time 返回时间戳+微秒
dbsize 返回key的数量
bgrewriteaof 重写aof
bgsave 后台开启子进程dump数据
save 阻塞进程dump数据
lastsave
slaveof host port 做host port的从服务器(数据清空,复制新主内容)
slaveof no one 变成主服务器(原数据不丢失,一般用于主服失败后)
flushdb 清空当前数据库的所有数据
flushall 清空所有数据库的所有数据(误用了怎么办?)
shutdown [save/nosave] 关闭服务器,保存数据,修改AOF(如果设置)
slowlog get 获取慢查询日志
slowlog len 获取慢查询日志条数
slowlog reset 清空慢查询

info []

config get 选项(支持*通配)
config set 选项 值
config rewrite 把值写到配置文件
config restart 更新info命令的信息

debug object key #调试选项,看一个key的情况
debug segfault #模拟段错误,让服务器崩溃
object key (refcount|encoding|idletime)
monitor #打开控制台,观察命令(调试用)
client list #列出所有连接
client kill #杀死某个连接 CLIENT KILL 127.0.0.1:43501
client getname #获取连接的名称 默认nil
client setname "名称" #设置连接名称,便于调试

配置Redis多实例

cp redis.conf redis_6378.conf
mv redis.conf redis_6379.conf #将原文件改名
[root@demo1 redis-6.0.6]# vim redis_6378.conf #修改6378实例配置项
设置内存使用限制,测试环境暂不设置
 113 timeout 3600
 244 pidfile /var/run/redis_6378.pid
 257 logfile "redis_6378.log"
 339 dbfilename dump_6378.rdb
 362 dir /var/run/
[root@demo1 ~]# ./redis_service.sh 6378 start
Redis server v=6.0.6 sha=00000000:0 malloc=jemalloc-5.1.0 bits=64 build=8984173731f15c3
Redis server(port:6378) is stared...
[root@demo1 ~]# ps -ef | grep redis
root      30048      1  0 16:40 ?        00:00:03 /usr/bin/redis-server 127.0.0.1:6379
root      30274      1  0 17:10 ?        00:00:00 /usr/bin/redis-server 127.0.0.1:6378

主从同步

IP地址 端口 角色
192.168.245.100 6379 master
192.168.245.100 6378 slave
192.168.245.110 6379 slave
192.168.245.110 6378 slave

master查看redis角色

192.168.245.100:6379> INFO replication
# Replication
role:master
connected_slaves:0
master_replid:0b9dc1e36b754dcd0d432a2e8b978c06371f0aae
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:2661
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:2661

slave服务器查看下角色

192.168.245.100:6378> INFO replication
# Replication
role:master
connected_slaves:0
master_replid:a51e71782eef3688e746a30fc532545dcf9c1597
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

编辑几个redis的配置文件设置监听本机地址

[root@demo1 redis-6.0.6]# vim redis_PORT.conf
···
  69 bind 192.168.245.100
···
[root@demo2 redis-6.0.6]# vim redis_PORT.conf
···
  69 bind 192.168.245.110
···
从服务器配置master的地址
[root@demo1 ~]# redis-cli -h 192.168.245.100 -p 6378
192.168.245.100:6378> SLAVEOF 192.168.245.100 6379
OK
192.168.245.100:6378> CONFIG REWRITE
OK
[root@demo2 ~]# redis-cli -h 192.168.245.110 -p 6378
192.168.245.110:6378> SLAVEOF 192.168.245.100 6379
OK
192.168.245.110:6378> CONFIG REWRITE
OK
[root@demo2 ~]# redis-cli -h 192.168.245.110 -p 6379
192.168.245.110:6379> SLAVEOF 192.168.245.100 6379
OK
192.168.245.110:6379> CONFIG REWRITE
OK

Redis Config rewrite 命令对启动 Redis 服务器时所指定的 redis.conf 配置文件进行改写。
使用CONFIG REWRITE命令会将配置保存在redis.conf如下,下次启动时会自动加载
或者不执行以上命令,直接将replicaof 192.168.245.100 6379写入从服务器的配置文件

  • 1836 replicaof 192.168.245.100 6379

配置完成后主从已经配置完毕,再查看下master的redis角色

192.168.245.100:6379> INFO replication
# Replication
role:master
connected_slaves:3
slave0:ip=192.168.245.100,port=6378,state=online,offset=3669,lag=0
slave1:ip=192.168.245.110,port=6378,state=online,offset=3669,lag=0
slave2:ip=192.168.245.110,port=6379,state=online,offset=3669,lag=0
master_replid:0b9dc1e36b754dcd0d432a2e8b978c06371f0aae
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:3683
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:3683

测试主从同步

192.168.245.100:6379> set hello world
OK
192.168.245.110:6379> get hello
"world"

redis(Sentinel)哨兵机制

IP地址 端口 角色
192.168.245.100 6379 master
192.168.245.100 6378 slave1
192.168.245.110 6379 slave2
192.168.245.100 23769 Sentinel1
192.168.245.100 23768 Sentinel2
192.168.245.110 23769 Sentinel3

Redis哨兵机制
主从切换技术的方法是:当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费事费力,还会造成一段时间内服务不可用。这不是一种推荐的方式,更多时候,我们优先考虑哨兵模式。
哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。

通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器。
当哨兵监测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机。

一个哨兵进程对Redis服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式。
用文字描述一下故障切换(failover)的过程。假设主服务器宕机,Sentinel1先检测到这个结果,系统并不会马上进行failover过程,仅仅是Sentinel1主观的认为主服务器不可用,这个现象成为主观下线。当后面的Sentinel也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个Sentinel发起,进行failover操作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线。这样对于客户端而言,一切都是透明的。
配置:

配置前需要配置好主从,以下在主从配置完成后操作

[root@demo1 redis-6.0.6]# pwd
/usr/local/redis-6.0.6
[root@demo1 redis-6.0.6]# cp sentinel.conf sentinel_6378.conf
[root@demo1 redis-6.0.6]# cp sentinel.conf sentinel_6379.conf
[root@demo1 redis-6.0.6]# vim sentinel_6378.conf
 21 port 26378
# 一台机器起多个,防止端口冲突进行修改,默认为26379
 26 daemonize yes
 31 pidfile "/var/run/redis-sentinel_6378.pid"
 36 logfile "/var/log/sentinel_6378.log"
 86 # sentinel auth-pass <master-name> <password>
# 连接master和slave时的密码
141 sentinel monitor mymaster 192.168.245.100 6379 2
# 如果有三台哨兵,那么主观上有两台认为master宕机才会选举新的master
166 sentinel failover-timeout mymaster 10000
# 需要多少时间一个master才会被这个sentinel主观地认为是不可用的(单位:毫秒)默认30s

其他两台从Redis配置除端口外大致相同
启动sentinel

/usr/bin/redis-sentinel /usr/local/redis-6.0.6/sentinel_6379.conf (对应配置文件需要修改)
[root@demo1 ~]# ps -ef | grep redis
root       1858      1  0 10:22 ?        00:00:09 /usr/bin/redis-server 192.168.245.100:6378
root       1885      1  0 10:22 ?        00:00:09 /usr/bin/redis-server 192.168.245.100:6379
root       2022      1  0 11:29 ?        00:00:01 /usr/bin/redis-sentinel *:26379 [sentinel]
root       2028      1  1 11:29 ?        00:00:01 /usr/bin/redis-sentinel *:26378 [sentinel]

查看下master信息

[root@demo1 ~]# cat redis
PORT=$1
/usr/bin/redis-cli -h 192.168.245.100 -p $PORT
[root@demo1 ~]# chmod +x redis
[root@demo1 ~]# ./redis 6379
192.168.245.100:6379> INFO replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.245.110,port=6379,state=online,offset=89145,lag=0
slave1:ip=192.168.245.100,port=6378,state=online,offset=89145,lag=0
master_replid:ca9a9813cf71c58bd7dd57dd1e9655de9c2d6716
master_replid2:8422b902f5cb0792b38355b230906f823517ce16
master_repl_offset:89435
second_repl_offset:69399
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:89435

将master停止,验证是否会重新进行选举

[root@demo1 ~]# ./redis_service.sh 6379 stop
[root@demo1 ~]# ./redis 6378
192.168.245.100:6378> INFO replication
# Replication
role:slave
master_host:192.168.245.100
master_port:6379
master_link_status:down
master_last_io_seconds_ago:-1
master_sync_in_progress:0
slave_repl_offset:132524
master_link_down_since_seconds:4
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:ca9a9813cf71c58bd7dd57dd1e9655de9c2d6716
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:132524
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:79787
repl_backlog_histlen:52738
# 经过master_link_down_since_seconds:读秒30,成功切换为slave2为master
192.168.245.100:6378> INFO replication
# Replication
role:slave
master_host:192.168.245.110
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:133431
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:5bddaa0ac2dd6040135978929b5ee72b254a1897
master_replid2:ca9a9813cf71c58bd7dd57dd1e9655de9c2d6716
master_repl_offset:133431
second_repl_offset:132525
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:79787
repl_backlog_histlen:53645

在新master slave2上写一个数据,看master启动后是否能够进行同步

[root@demo2 ~]# ./redis 6379
192.168.245.110:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.245.100,port=6378,state=online,offset=198376,lag=0
master_replid:5bddaa0ac2dd6040135978929b5ee72b254a1897
master_replid2:ca9a9813cf71c58bd7dd57dd1e9655de9c2d6716
master_repl_offset:198376
second_repl_offset:132525
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:65433
repl_backlog_histlen:132944
192.168.245.110:6379> set 111 222
OK
192.168.245.110:6379> get 111
"222"
192.168.245.100:6378> get 111
"222"
------------------------------------------------
[root@demo1 ~]# ./redis_service.sh 6379 start
Redis server v=6.0.6 sha=00000000:0 malloc=jemalloc-5.1.0 bits=64 build=8984173731f15c3
Redis server(port:6379) is stared...
[root@demo1 ~]# ./redis 6379
192.168.245.100:6379> get 111
(nil)
192.168.245.100:6379> get 111
"222"

Redis持久化

持久化:将数据(如内存中的对象)保存到可永久保存的存储设备中。

Redis提供如下三种持久化方式:

  • 快照方式(RDB, Redis DataBase)将某一个时刻的内存数据,以二进制的方式写入磁盘;
  • 文件追加方式(AOF, Append Only File),记录所有的操作命令,并以文本的形式追加到文件中;
  • 混合持久化方式,Redis 4.0 之后新增的方式,混合持久化是结合了 RDB 和 AOF 的优点,在写入的时候,先把当前的数据以 RDB 的形式写入文件的开头,再将后续的操作命令以 AOF 的格式存入文件,这样既能保证 Redis 重启时的速度,又能简单数据丢失的风险。

RDB与AOF对比

快照方式RDB

优势

  • RDB 的内容为二进制的数据,占用内存更小,更紧凑,更适合做为备份文件。

  • 生成RDB文件的时候,redis主进程会fork()一个子进程来处理所有保存工作,主进程不需要进行任何磁盘IO操作。

  • RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
    劣势

  • RDB快照是一次全量备份,存储的是内存数据的二进制序列化形式,存储上非常紧凑。当进行快照持久化时,会开启一个子进程专门负责快照持久化,子进程会拥有父进程的内存数据,父进程修改内存子进程不会反应出来,所以在快照持久化期间修改的数据不会被保存,可能丢失数据。

文件追加方式AOF

优点

  • AOF可以更好的保护数据不丢失,一般AOF会每隔1秒,通过一个后台线程执行一次fsync操作,最多丢失1秒钟的数据。(2)AOF日志文件没有任何磁盘寻址的开销,写入性能非常高,文件不容易破损。

  • AOF日志文件即使过大的时候,出现后台重写操作,也不会影响客户端的读写。

  • AOF日志文件的命令通过非常可读的方式进行记录,这个特性非常适合做灾难性的误删除的紧急恢复。比如某人不小心用flushall命令清空了所有数据,只要这个时候后台rewrite还没有发生,那么就可以立即拷贝AOF文件,将最后一条flushall命令给删了,然后再将该AOF文件放回去,就可以通过恢复机制,自动恢复所有数据

缺点

  • 对于同一份数据来说,AOF日志文件通常比RDB数据快照文件更大

  • AOF开启后,支持的写QPS会比RDB支持的写QPS低,因为AOF一般会配置成每秒fsync一次日志文件,当然,每秒一次fsync,性能也还是很高的

  • 以前AOF发生过bug,就是通过AOF记录的日志,进行数据恢复的时候,没有恢复一模一样的数据出来。

持久化配置

RDB持久化

RDB的持久化触发方式有两类:一类是手动触发,另一类是自动触发。、

手动触发

手动触发持久化的操作有两个:savebgsave ,它们主要区别体现在:是否阻塞 Redis 主线程的执行。

1、save 命令

在客户端中执行 save 命令,就会触发 Redis 的持久化,但同时也是使 Redis 处于阻塞状态,直到 RDB 持久化完成,才会响应其他客户端发来的命令,所以在生产环境一定要慎用。
Redis_save

2、bgsave 命令

bgsave(background save)既后台保存的意思, 它和 save 命令最大的区别就是 bgsave 会 fork() 一个子进程来执行持久化,整个过程中只有在 fork() 子进程时有短暂的阻塞,当子进程被创建之后,Redis 的主进程就可以响应其他客户端的请求

自动触发

1、save m n

save m n 是指在 m 秒内,如果有 n 个键发生改变,则自动触发持久化。配置文件中默认为开启

[root@demo1 redis-6.0.6]# vim redis_6379.conf
 304 save 900 1
 305 save 300 10
 306 save 60 10000

2、flushall

flushall 命令用于清空 Redis 数据库,在生产环境下一定慎用,当 Redis 执行了 flushall 命令之后,则会触发自动持久化,把 RDB 文件清空。

3、主从同步触发

在 Redis 主从复制中,当从节点执行全量复制操作时,主节点会执行 bgsave 命令,并将 RDB 文件发送给从节点,该过程会自动触发 Redis 持久化。

RDB可配置参数

# RDB 保存的条件
save 900 1
save 300 10
save 60 10000
# bgsave 失败之后,是否停止持久化数据到磁盘,yes 表示停止持久化,no 表示忽略错误继续写文件。
stop-writes-on-bgsave-error yes
# RDB 文件压缩
rdbcompression yes
# 写入文件和读取文件时是否开启 RDB 文件检查,检查是否有无损坏,如果在启动是检查发现损坏,则停止启动。
rdbchecksum yes
# RDB 文件名
dbfilename dump.rdb
# RDB 文件目录
dir ./

RDB文件恢复

当 Redis 服务器启动时,如果 Redis 根目录存在 RDB 文件 dump.rdb,Redis 就会自动加载 RDB 文件恢复持久化数据。
如果根目录没有 dump.rdb 文件,请先将 dump.rdb 文件移动到 Redis 的根目录。
Redis 在启动时有日志信息,会显示是否加载了 RDB 文件

AOF持久化

默认是不开启 AOF 的,如果想要启用则需要到 redis.conf 配置文件中开启

[root@demo1 redis-6.0.6]# vim redis_6379.conf
1059 appendonly yes
1063 appendfilename "/var/run/appendonly.aof"
1088 # appendfsync always
1089 appendfsync everysec
1090 # appendfsync no
1130 auto-aof-rewrite-percentage 100
1131 auto-aof-rewrite-min-size 64mb
1155 aof-load-truncated yes

AOF的三种持久化模式

  • appendfsync always 每次收到写命令就立即强制写入磁盘,是最有保证的完全的持久化,但速度也是最慢的,一般不推荐使用。

  • appendfsync everysec 每秒种强制写入磁盘一次,在性能与持久化方面做了折中,也是最受欢迎的方式。

  • appendfsync no 完全依赖OS的写入,一般为30秒左右一次,性能最好,但是持久化最没有保障,不被推荐。

AOF的工作流程

1、所有的写入命令会追加到aof_buf(缓冲区)中。

2、AOF缓冲区根据对应的策略向硬盘做同步操作。

3、随着AOF文件越来越大,需要定期对AOF文件进行重写,达到压缩的目的。

4、当Redis服务器重启时,可以加载AOF文件进行数据恢复。

重写机制

随着命令不断写入AOF,文件会越来越大,为了解决这个问题,Redis引入AOF重写机制压缩文件体积。AOF文件重写是把Redis进程内的数据转化为写命令同步到新AOF文件的过程。通俗的理解就是AOF采用文件追加方式,文件会越来越大为避免出现此种情况,新增了重写机制,当AOF文件的大小超过所设定的阈值时,Redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集.可以使用命令bgrewriteaof。

原理 : AOF文件持续增长而过大时,会fork出一条新进程来将文件重写(也是先写临时文件最后再rename),遍历新进程的内存中数据,每条记录有一条的Set语句。重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点类似

AOF重写过程可以手动触发和自动触发:

  • 手动触发:直接调用bgrewriteaof命令。

  • 自动触发:根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参数确定自动触发时机。Redis会记录上次重写时的AOF大小,默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发

数据文件损坏如何修复

对于错误格式的AOF文件,先进行备份,然后采用redis-check-aof--fix命令进行修复,修复后使用diff-u对比数据的差异,找出丢失的数据,有些可以人工修改补全。AOF文件可能存在结尾不完整的情况,比如机器突然掉电导致AOF尾部文件命令写入不全。Redis为我们提供了aof-load-truncated配置来兼容这种情况,默认开启。加载AOF时,当遇到此问题时会忽略并继续启动。

混合持久化

[root@demo1 redis-6.0.6]# vim redis_6379.conf
1166 aof-use-rdb-preamble yes

重启redis恢复数据集时,很少会使用rdb来恢复内存状态,因为会丢失大量数据。通常会使用aof日志恢复数据,但是重放aof日志性能相对rdb来说要慢很多,这样在redis实例很大的情况下,启动需要花费很长时间。Redis4.0为了解决这个问题,带来了新的持久化选项:混合持久化。
混合持久化aof文件结构:
混合持久化aof文件
如果开启了混合持久化,aof在重写时,不再是单纯将内存数据转换为RESP命令写入aof文件,而是将重写这一刻之前的内存做rdb快照处理,并且将rdb快照内容和增量的aof修改内存数据的命令存在一起,都写入新的aof文件,新的aof文件一开始不叫appendonly.aof,等到重写完成后,新的aof文件才会进行改名,原子的覆盖原有的aof文件,完成新旧两个aof文件的替换。
于是在redis重启的时候,可以先加载rdb文件,然后再重放增量的aof日志就可以完全替代之前的aof全量文件重放,因此重启效率大幅得到提高。

Redis cluster集群部署

sentinel模式基本可以满足一般生产的需求,具备高可用性。但是当数据量过大到一台服务器存放不下的情况时,主从模式或sentinel模式就不能满足需求了,这个时候需要对存储的数据进行分片,将数据存储到多个Redis实例中。cluster模式的出现就是为了解决单机Redis容量有限的问题,将Redis的数据根据一定的规则分配到多台机器。
cluster可以说是sentinel和主从模式的结合体,通过cluster可以实现主从和master重选功能,所以如果配置两个副本三个分片的话,就需要六个Redis实例。因为Redis的数据是根据一定规则分配到cluster的不同机器的,当数据量过大时,可以新增机器进行扩容。
使用集群,只需要将redis配置文件中的cluster-enable配置打开即可。每个集群中至少需要三个主数据库才能正常运行,新增节点非常方便。

  • 多个redis节点网络互联,数据共享

  • 所有的节点都是一主一从(也可以是一主多从),其中从不提供服务,仅作为备用

  • 不支持同时处理多个key(如MSET/MGET),因为redis需要把key均匀分布在各个节点上,并发量很高的情况下同时创建key-value会降低性能并导致不可预测的行为

  • 支持在线增加、删除节点

  • 客户端可以连接任何一个主节点进行读写

序号 IP地址 端口
1 192.168.245.100 6377
2 192.168.245.100 6378
3 192.168.245.100 6379
4 192.168.245.110 6377
5 192.168.245.110 6378
6 192.168.245.110 6379
创建配置文件
[root@demo1 redis-6.0.6]# ls | grep redis
redis_6377.conf
redis_6378.conf
redis_6379.conf
[root@demo1 redis-6.0.6]# vim redis_6377.conf
下为需要注意的配置,其他配置忽略,不代表不需要配置
 392 masterauth "123123"
 786 requirepass "123123"
1059 appendonly yes
1192 cluster-enabled yes
1200 cluster-config-file nodes-6377.conf
1206 cluster-node-timeout 15000
其余几个配置大致相同,此处忽略

Redis5版本之前的需要使用Ruby创建集群

[root@demo1 ~]# redis-trib.rb create --replicas 1 192.168.245.100:6377 192.168.245.110:6378 192.168.245.100:6379 192.168.245.110:6377 192.168.245.100:6378 192.168.245.110:6379  
# create 创建 replicas 副本一个 前3个节点会被认为是主节点  后3个节点会被认为是从节点

Redis5.0之后使用redis-cli作为创建集群的命令,使用c语言实现,不再使用ruby语言。

[root@demo1 ~]# redis-cli -a 123123 --cluster create 192.168.245.100:6377 192.168.245.110:6378 192.168.245.100:6379 192.168.245.110:6377 192.168.245.100:6378 192.168.245.110:6379 --cluster-replicas 1
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 192.168.245.110:6379 to 192.168.245.100:6377
Adding replica 192.168.245.100:6378 to 192.168.245.110:6378
Adding replica 192.168.245.110:6377 to 192.168.245.100:6379
M: cf73644433de26abecb1e33dd691d64bedb87d5b 192.168.245.100:6377
   slots:[0-5460] (5461 slots) master
M: afbc4880858827b6d6544c3ca9e06b16b335fc14 192.168.245.110:6378
   slots:[5461-10922] (5462 slots) master
M: 46e2e32ac3ffe240f553ade3b291a93c39060194 192.168.245.100:6379
   slots:[10923-16383] (5461 slots) master
S: 0c20398cfd830a43202107c2cc01f48855b639e2 192.168.245.110:6377
   replicates 46e2e32ac3ffe240f553ade3b291a93c39060194
S: 559ddf170dbbd8eaafd83bb1162dfdcb2e6abf26 192.168.245.100:6378
   replicates afbc4880858827b6d6544c3ca9e06b16b335fc14
S: 6eac9352b9f6ef40de32958830f8c462ad678548 192.168.245.110:6379
   replicates cf73644433de26abecb1e33dd691d64bedb87d5b
Can I set the above configuration? (type 'yes' to accept): yes   #yes代表接收上面的配置
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
.
>>> Performing Cluster Check (using node 192.168.245.100:6377)
M: cf73644433de26abecb1e33dd691d64bedb87d5b 192.168.245.100:6377
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: 6eac9352b9f6ef40de32958830f8c462ad678548 192.168.245.110:6379
   slots: (0 slots) slave
   replicates cf73644433de26abecb1e33dd691d64bedb87d5b
S: 559ddf170dbbd8eaafd83bb1162dfdcb2e6abf26 192.168.245.100:6378
   slots: (0 slots) slave
   replicates afbc4880858827b6d6544c3ca9e06b16b335fc14
S: 0c20398cfd830a43202107c2cc01f48855b639e2 192.168.245.110:6377
   slots: (0 slots) slave
   replicates 46e2e32ac3ffe240f553ade3b291a93c39060194
M: afbc4880858827b6d6544c3ca9e06b16b335fc14 192.168.245.110:6378
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
M: 46e2e32ac3ffe240f553ade3b291a93c39060194 192.168.245.100:6379
   slots:[10923-16383] (5461 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.

可以看到

Adding replica 192.168.245.110:6379 to 192.168.245.100:6377
Adding replica 192.168.245.100:6378 to 192.168.245.110:6378
Adding replica 192.168.245.110:6377 to 192.168.245.100:6379
192.168.245.100:6377 的从服务器是 192.168.245.110:6379
192.168.245.110:6378 的从服务器是 192.168.245.100:6378
192.168.245.100:6379 的从服务器是 192.168.245.110:6377

查看自动生成的nodes.conf文件

[root@demo1 run]# ls -lrth | grep node
-rw-r--r--.  1 root   root    817 8月   7 14:49 nodes-6378.conf
-rw-r--r--.  1 root   root    817 8月   7 14:49 nodes-6379.conf
-rw-r--r--.  1 root   root    817 8月   7 14:49 nodes-6377.conf
[root@demo1 run]# cat nodes-6377.conf 
6eac9352b9f6ef40de32958830f8c462ad678548 192.168.245.110:6379@16379 slave cf73644433de26abecb1e33dd691d64bedb87d5b 0 1596782967424 1 connected
559ddf170dbbd8eaafd83bb1162dfdcb2e6abf26 192.168.245.100:6378@16378 slave afbc4880858827b6d6544c3ca9e06b16b335fc14 0 1596782966411 2 connected
0c20398cfd830a43202107c2cc01f48855b639e2 192.168.245.110:6377@16377 slave 46e2e32ac3ffe240f553ade3b291a93c39060194 0 1596782965000 3 connected
afbc4880858827b6d6544c3ca9e06b16b335fc14 192.168.245.110:6378@16378 master - 0 1596782964397 2 connected 5461-10922
46e2e32ac3ffe240f553ade3b291a93c39060194 192.168.245.100:6379@16379 master - 0 1596782965394 3 connected 10923-16383
cf73644433de26abecb1e33dd691d64bedb87d5b 192.168.245.100:6377@16377 myself,master - 0 1596782963000 1 connected 0-5460
vars currentEpoch 6 lastVoteEpoch 0

登录集群redis-cli -c -c,使用集群方式登录

[root@demo1 ~]# redis-cli -c -h 192.168.245.100 -p 6377 -a 123123
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.245.100:6377> CLUSTER INFO   #查看集群状态
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:412
cluster_stats_messages_pong_sent:419
cluster_stats_messages_sent:831
cluster_stats_messages_ping_received:414
cluster_stats_messages_pong_received:412
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:831
192.168.245.100:6377> CLUSTER NODES   #列出节点信息,与nodes.conf文件内容相同
6eac9352b9f6ef40de32958830f8c462ad678548 192.168.245.110:6379@16379 slave cf73644433de26abecb1e33dd691d64bedb87d5b 0 1596783403927 1 connected
559ddf170dbbd8eaafd83bb1162dfdcb2e6abf26 192.168.245.100:6378@16378 slave afbc4880858827b6d6544c3ca9e06b16b335fc14 0 1596783404942 2 connected
0c20398cfd830a43202107c2cc01f48855b639e2 192.168.245.110:6377@16377 slave 46e2e32ac3ffe240f553ade3b291a93c39060194 0 1596783402000 3 connected
afbc4880858827b6d6544c3ca9e06b16b335fc14 192.168.245.110:6378@16378 master - 0 1596783403000 2 connected 5461-10922
46e2e32ac3ffe240f553ade3b291a93c39060194 192.168.245.100:6379@16379 master - 0 1596783404000 3 connected 10923-16383
cf73644433de26abecb1e33dd691d64bedb87d5b 192.168.245.100:6377@16377 myself,master - 0 1596783403000 1 connected 0-5460
192.168.245.100:6377> 

插入数据测试

192.168.245.100:6377> set 001 001
-> Redirected to slot [9794] located at 192.168.245.110:6378    #说明数据被分配在192.168.245.110:6378节点上
OK
192.168.245.110:6378> set 002 002
OK
192.168.245.110:6378> set 003 003
-> Redirected to slot [1536] located at 192.168.245.100:6377    #说明数据被分配在192.168.245.100:6377节点上
OK
192.168.245.100:6377> set 004 004
-> Redirected to slot [14055] located at 192.168.245.100:6379    #说明数据被分配在192.168.245.100:6379节点上
OK
[root@demo1 ~]# redis-cli -c -h 192.168.245.110 -p 6379 -a 123123
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.245.110:6379> get 001
-> Redirected to slot [9794] located at 192.168.245.110:6378
"001"
192.168.245.110:6378> get 003
-> Redirected to slot [1536] located at 192.168.245.100:6377
"003"
192.168.245.100:6377> get 004
-> Redirected to slot [14055] located at 192.168.245.100:6379
"004"
  • 可以看出redis cluster集群是去中心化的,每个节点都是平等的,连接哪个节点都可以获取和设置数据。
  • 当然,平等指的是master节点,因为slave节点根本不提供服务,只是作为对应master节点的一个备份。
    在192.168.245.100与110两台主机上新增一个redis节点
cp redis_6377.conf redis_6376.conf
vim redis_6376.conf
:%s/6377/6376/g
:wq

集群增加slave节点

  • 192.168.245.110:6378> CLUSTER MEET 节点IP PORT 不推荐直接增加,建议slave节点添加给指定master节点,见下文。

集群删除添加的slave节点

  • redis-cli --cluster del-node 节点ip:port 节点id

删除 master 节点

  • 先对节点进行分片工作,防止数据丢失
  •   `redis-cli --cluster reshard 欲删除节点ip:port`
    
  • 移除节点
  •   `redis-cli --cluster del-node 节点ip:port 节点id`
    

新增master节点

redis-cli --cluster add-node 192.168.245.100:6376 192.168.245.100:6377
  • 第一个ip:port 为需要添加的节点ip和端口,第二个ip:port为当前集群中的节点和端口

新加入集群的master节点没有哈希槽,并不能正常存储数据,需要给新添加的节点分配哈希槽:哈希槽的配置不均匀,可能导致数据不同步

分配哈希槽

  • ip:port 为当前redis集群任意节点ip和port,-a后面加密码
redis-cli --cluster reshard 192.168.245.100:6376 -a 123123

[root@demo1 ~]# redis-cli --cluster reshard 192.168.245.100:6376 -a 123123
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Performing Cluster Check (using node 192.168.245.100:6376)
M: f4f176f593b802a96c35baf0aadceb650de9cc83 192.168.245.100:6376
   slots: (0 slots) master
   1 additional replica(s)
M: afbc4880858827b6d6544c3ca9e06b16b335fc14 192.168.245.110:6378
   slots:[7282-10922] (3641 slots) master
   1 additional replica(s)
M: cf73644433de26abecb1e33dd691d64bedb87d5b 192.168.245.100:6377
   slots:[1820-5460] (3641 slots) master
   1 additional replica(s)
S: 559ddf170dbbd8eaafd83bb1162dfdcb2e6abf26 192.168.245.100:6378
   slots: (0 slots) slave
   replicates afbc4880858827b6d6544c3ca9e06b16b335fc14
S: 61aa3861de2dcb823c5ebf0913f076de013e6a12 192.168.245.110:6376
   slots: (0 slots) slave
   replicates f4f176f593b802a96c35baf0aadceb650de9cc83
S: 6eac9352b9f6ef40de32958830f8c462ad678548 192.168.245.110:6379
   slots: (0 slots) slave
   replicates cf73644433de26abecb1e33dd691d64bedb87d5b
M: 46e2e32ac3ffe240f553ade3b291a93c39060194 192.168.245.100:6379
   slots:[12743-16383] (3641 slots) master
   1 additional replica(s)
S: 0c20398cfd830a43202107c2cc01f48855b639e2 192.168.245.110:6377
   slots: (0 slots) slave
   replicates 46e2e32ac3ffe240f553ade3b291a93c39060194
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
How many slots do you want to move (from 1 to 16384)? 1000  #要分配多少个哈希槽(数量)?比如我要分配1000个哈希槽
What is the receiving node ID? f4f176f593b802a96c35baf0aadceb650de9cc83   #输入需要分配哈希槽的节点ID
Please enter all the source node IDs.
  Type 'all' to use all the nodes as source nodes for the hash slots.
  Type 'done' once you entered all the source nodes IDs.
Source node #1: all  #输入all 需要分配给目标节点的哈希槽来自当前集群的其他主节点(每个节点拿出的数量由集群自动决定)
            ······
    Moving slot 13073 from 46e2e32ac3ffe240f553ade3b291a93c39060194
    Moving slot 13074 from 46e2e32ac3ffe240f553ade3b291a93c39060194
    Moving slot 13075 from 46e2e32ac3ffe240f553ade3b291a93c39060194
Do you want to proceed with the proposed reshard plan (yes/no)? yes  #是否继续执行建议的reshard计划
输入yes后,就会完成分配哈希槽

进入redis客户端 cluster slots 查看(6376端口的主节点的原哈希槽数量为0)

192.168.245.100:6377> cluster slots
1) 1) (integer) 13076
   2) (integer) 16383
   3) 1) "192.168.245.100"
      2) (integer) 6379
      3) "46e2e32ac3ffe240f553ade3b291a93c39060194"
   4) 1) "192.168.245.110"
      2) (integer) 6377
      3) "0c20398cfd830a43202107c2cc01f48855b639e2"
2) 1) (integer) 0
   2) (integer) 2152
   3) 1) "192.168.245.100"
      2) (integer) 6376
      3) "f4f176f593b802a96c35baf0aadceb650de9cc83"

分配哈希槽有两种方式

  • 1、将所有节点用作哈希槽的源节点。:all
  • 2、在指定的节点拿出指定数量的哈希槽分配到目标节点:done

slave挂靠master

slave的添加方法,master为192.168.245.100:6376
节点ID是主节点(master)的ID

redis-cli --cluster add-node 192.168.245.110:6376 192.168.245.100:6377  --cluster-slave --cluster-master-id f4f176f593b802a96c35baf0aadceb650de9cc83 -a 123123
  • 192.168.245.110:6376 是新加的从节点
  • 192.168.245.100:6377 当前集群中的任意节点即作为从节点的主节点

强制删除master节点不做slot转移

  • 查看 redis.conf 文件中 dir 的配置路径
  • 在路径下删除关于该节点的 nodes-port(对应端口号).conf、.aof 和.rdb 文件
  • 最后再执行移除节点的命令
  • 如果要彻底移除集群,且不保存数据也可以使用该方式
  • 对于执行集群相关操作的时候出现错误,可以使用 redis-cli --cluster check ip:port 检查集群是否有错误,使用 redis-cli --cluster fix ip:port 修复相关错误(如:Not all 16384 slots are covered by nodes.)

保存集群配置

CLUSTER SAVECONFIG 将节点信息保存到硬盘

Redis集群cluster总结

  • master主节点实例最好分布在不同的服务器上,slave从节点实例也最好分布在不同的服务器上
  • master主节点实例和它自己所包括的从节点实例也最好分布在不同的服务器上,不要在同一个服务器上。部署redis cluster的机器如果是虚拟机,则虚拟机最好也别部署在同一台物理宿主机上。这样做是为了避免因服务器挂掉或主从节点机器全部挂掉,导致数据丢失,集群启用失败。
  • 如果redis机器挂掉的数量不超过集群机器总数量的1/2,那么redis集群服务将不受影响,可以继续使用。但是节点机器重启后,则它上面的redis节点实例加入到集群中后,它上面之前的master实例变为slave实例(这个master之前对应的slave将随之变为master),也就是说重启后这个节点的两个redis实例全部变为slave了(原来是一主一从,重启后两从)。
  • 如果redis机器挂掉的数量超过了集群机器总数量的1/2,则不仅要重启机器的redis服务,还要重新加入到redis cluster集群重新创建集群时,注意master和slave关系要和之前一样。
  • 千万注意redis cluster中的节点重启事会先从集中中踢出来,即它上面的master和slave实例会消失,master之前对应的slave变为新的master,待该节点重启成功后会自动重新加入到集群中,并全部成为slave实例。由于节点重启期间,在从集群中踢出来到自动重新加入到集群中存在一定的时间间隔,所以集群中的节点不能同时重启,也不能短时间内一起重启,否则会造成集群崩溃,集群数据丢失。一般而言,重启一台节点,待该节点重启后并检查成功重新加入到集群中够,再另外重启别的节点。

redis作为纯缓存服务时,数据丢失,一般对业务是无感的,不影响业务,丢失后会再次写入。但如果作为存储服务(即作为存储数据库),数据丢失则对业务影响很大。
不过一般业务场景,存储数据库会用mysql、oracle或mongodb。

posted @ 2020-07-28 15:39  Chuyio  阅读(506)  评论(0编辑  收藏  举报