Redis 持久化和集群

 

 

Redis持久化

redis将所有的数据都存储在内存中,所以访问速度很快,但是一旦 redis 重启,所有存储在 redis中的数据都会丢失。所以要持久化到硬盘中,重启以后可以恢复数据。

redis 持久化的方式有两种,一种是 RDB 方式,一种是 AOF 方式,

  • RDB 是按照规则,“定时”将内存中的数据持久化到硬盘中
  • AOF 者还是每次执行命令的时候,将命令本身保存下来

但是更多的时候,还是将两者结合起来使用

下面是使用宝塔安装的 redis 的配置界面

 

RDB方式(快照方式)

RDB方式就是通过快照 实现的,当符合一定条件的时候,就将所有的数据生成副本,保存到硬盘中,这个过程叫做快照。

自动快照

redis的快照条件,可以在配置文件里更改。

save 900 1
save 300 10
save 60 10000

每一行有两个参数:时间窗口、更改键的个数,可以同时保存多个条件,只要满足一个条件,电脑就会自动进行快照

手动快照

当服务器需要重启,手动迁移的时候,需要手动执行快照,redis提供两个命令来完成这一任务

#save命令
save         #同步快照,当快照执行的时候,会阻塞所有客户端请求

#bgsave命令
bgsave       #Background saving started,后台异步进行快照
lastsave     #查看异步是否成功,查看最后一次执行的时间戳

其他触发快照的情况

  1. 当执行 flushall 命令的时候,redis 会清楚数据库中所有的数据,不管有没有达到触发条件,redis 都会执行一次快照。
  2. 当执行主从复制的时候,会生成 RDB 快照

RDB原理(快照原理)

Redis默认将文件存储在dump.rdb文件中,名称和路径可以自己更改

快照过程

  1. Redis会启动子进程使用 fork 函数复制当前进程的副本
  2. 父进程继续接受处理客户端请求,子进程开始将内存中的数据写入临时文件
  3. 当写完临时文件,子进程会用临时文件替换旧的 RDB 文件

快照方式持久化存在的问题

使用 RDB 实现持久化,一旦 redis 异常退出,这样会丢掉最后一次快照后更改的所有数据,但是一般影响并不大,但是如果数据相对来说比较重要,希望将损失降到最低,还需要使用 AOF实现持久化


AOF方式(append only file)

AOF可以将Redis执行的每一条写命令追加到磁盘文件中,这一过程显然会降低redis的性能,但是大部分情况下是可以接受的,而且还可以使用较快的硬盘来提高AOF的性能。

开启

如果是使用的宝塔安装的,可以直接把下面的选项打开,如果是原始安装的,可以通过参数来启动

AOF的优化

例如下面的例子,执行了三条 redis 命令

set f1 1
set f2 2
set f3 3

但是我们可以看出来,其实前两条是冗余的,因为前两条会别第三条覆盖掉,我们当然希望Redis自动优化 aof文件,删除无用的记录,显然redis也是这样做的。当达到一定的条件,就会重写 AOF 文件。

auto-aof-rewrite-percentage 100  #当内容超过上次内容的100%的时候,就会发生重写
auto-aof-rewrite-min-size 64mb   #限制了自动重写的大小,即内容比较少的似乎,即使翻很多倍,也不会重写

当然也可以手动重写

bgrewriteaof  #手动重写命令

同步硬盘数据

上图中的第二个选项appendfsync是用来设置同步的时机的,这个是因为AOF会将命令记录在AOF文件中,但是事实上,由于操作系统的缓存机制,数据并不会真正的写入到磁盘上,而是写入了磁盘缓存,所以上面的选项就是选择多久写一次。一般是 1秒,写的太频繁会影响性能。

Redis的主从复制

主从复制和 mysql 的主从复制道理差不多

  1. 主数据库可以进行读写操作,当操作导致数据变化,可以自动同步给从数据库
  2. 从数据库一般只读,并接受从主数据库中同步过来的数据
  3. 一个主数据库可以有多个从数据库,而一个从数据库,只能有一个主数据库。

配置主从复制

#开启一个redis,端口号6380,作为6379端口的从库
redis-server --port 6380 --slaveof 127.0.0.1 6379

redis-cli            #打开默认的6379的客户端
redis-cli -p 6380    #新开一个窗口,打开6380的客户端

结果如下

经过测试,发现从库只能读,不能写。

查看主从数据库配置

分别在主从库里执行如下命令,查看主从复制情况

info replication

主库info信息

# Replication
role:master                                                  #角色
connected_slaves:2                                           #几个从库
slave0:ip=127.0.0.1,port=6380,state=online,offset=950,lag=1  #从库 1
slave1:ip=127.0.0.1,port=6388,state=online,offset=950,lag=1  #从库 2
master_replid:c8c89aadcb4f0759db4d091c307cbbe60e5bbb98
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:950
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:950

从库info信息

role:slave                 #角色
master_host:127.0.0.1      #端口号
master_port:6379           #主表端口号
master_link_status:up
master_last_io_seconds_ago:9
master_sync_in_progress:0
slave_repl_offset:1188
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:c8c89aadcb4f0759db4d091c307cbbe60e5bbb98
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1188
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:1188

主从复制原理

复制过程

  1. 当一个从数据库启动的时候,会向主数据库发送 SYNC 命令。
  2. 主数据库收到命令后,会立刻在后台保存快照,并将此期间收到的数据缓存起来
  3. 主数据库将快照和所有的缓存命令发给从数据库
  4. 复制初始化完成以后,主数据库每当收到写命令,就会将数据同步给从数据库,以保证主从数据库的一致性

断网重连

Redis2.8以后,当数据库断网以后,主数据库只需要将断线期间执行的命令传给从数据库,而2.8之前的版本,是进行重新的初始化。这里用到的技术就是有条件的增量数据传输。

从数据库持久化

为了保证主数据库性能,可以使用一个或多个从数据库来实现持久化,而不是在主数据库中。

哨兵

在典型的一主多重的 redis系统中,当一个主数据库遇到异常中断服务,开发者可以手动的选择一个从数据库来升格为主数据库,但是整个过程如果都需要人工介入有点太麻烦,难以实现自动化。所以redis2.8以后,实现自动化的系统监控和古故障恢复功能
所以哨兵的主要作用有两个:

  • 监控主数据库和从数据库是否正常运行
  • 主数据库出现故障,自动把从数据库转成主数据库

哨兵的部署

首先开启两个 redis 服务

redis-server --port 6380 --slaveof 127.0.0.1 6379  #从库 1
redis-server --port 6381 --slaveof 127.0.0.1 6379  #从库 2

在任意一个文件夹下建立如下文件
建立文件夹sentinel.conf,文件名随便

# 最后的 1 ,表示的是最低投票数
# 其次注意,我们写哨兵,只需要监控主数据库就可以了,其他的都自会关联

sentinel monitor myredis_sentinel 127.0.0.1 6379 1

这样的话,哨兵模式就启动了,如果主机挂掉,其他的就会自动更新成主数据库