Redis 高级特性(主从复制、事务控制、持久化机制)

本文探讨Redis的主从复制机制,包括其必要性、特点、工作原理及配置方法,同时介绍了Redis事务控制,包括命令详解及执行过程,帮助读者深入理解Redis的高级特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. Redis 主从复制及操作

1.1 为什么要用主从复制
  • 一般来说,要将 Redis 用于工程项目中,只使用一台 Redis 那是万万不能的。原因如下:
    • 从结构上来说,单个 Redis 服务器会发生单点故障,并且一台服务器要处理所有的请求,负荷容易过载。
    • 从容量上,单个 Redis 服务器内存容量是有限的,就算 Redis 服务器内存容量为 256 G,也不能将所有的内容用作 Redis 存储内存。一般来说,单台 Redis 最大使用内存不应超过 20 G。
1.2 主从复制的特点
  • Master(主)可以有多个 Slave(从)。
  • 除了多个 Slave 连接相同的 Master 之外,Slave 之间也可以相互互联。
  • 主从复制不会阻塞 Master。也就是说,当一个或多个 Slave 与 Master 进行同步数据的时候,Master 可以继续处理客户端发来的请求。相反,Slave 在初次同步数据的时候,则会阻塞,不能处理客户端发来的请求。
  • 主从复制可以提高系统的可伸缩性。可以用多个 Slave 专门处理客户端的读请求。写服务仍需由 Master 完成。
  • Master 可以将数据存储交给 Slave 完成。从而避免了 Master 中要有独立的进程来完成此操作。
1.3 主从复制的好处
  • 读写分离。不仅可以提高服务器的负载能力,而且可以根据读请求的规模自由增加或减少从库的数量。
  • 数据被复制成了好几份,就算有一台机器出现了故障,也可以使用其他机器的数据快速恢复。但是这里需要注意的是,在 Redis 主从复制模式中,一台主机可以拥有多个从库,但是一个从库只能隶属于一个主机。
1.4 主从复制的工作原理
  • Slave 启动连接 Master 之后
  • Slave 会主动发送一个 SYNC 命令
  • 此后,Master 将启动后台存盘进程,同时收集所有接收到的用于修改数据集的命令。
  • 在后台进程执行完毕之后,Master 将传送整个数据库文件到 Slave,以完成一次完全的同步。
  • 而 Slave 服务器在接收到数据库文件之后,将其存盘并加载到内存中。
  • 此后 Master 继续将所有已收集到的修改命令和新的修改命令依次传送给 Slave。
  • Slave 将在本次执行这些数据的修改,从而最终达到数据的同步。
  • 在这个过程中,如果 Master 和 Slave 出现断连现象,Slave 可以重新自动连接 Master。但是在连接成功之后,一次完全同步将会被自动执行。
1.5 如何实现主从复制
  • 既然是主从复制,那肯定要启动两个 Redis 服务器。
  • 我们这里采用的方法是:在同一台机器上,启动两个 Redis 服务器,分别监听不同的端口。
  • 这里使用 6379 和 6380 两个端口。
# 进入到 Redis 配置文件所在文件夹
cd /usr/local/redis/etc

# 复制出两份配置文件
cp redis.conf 6379.conf
cp redis.conf 6380.conf

# 先修改 6379.conf (之后作为 master)
vim 6379.conf
## 1. 修改日志地址文件名称
/logfile
# 将
logfile ""
# 改为
logfile "6379.log"

## 2. 修改数据库备份文件名称
/dbfile
# 将
dbfilename dump.rdb
# 改为
dbfilename dump6379.rdb

# 再修改 6380.conf(之后作为 slave)
vim 6380.conf
## 1. 修改监听端口
/port 6379
# 将
port 6379
# 改为
port 6380

## 2. 修改 pidfile
/pidfile
# 将
pidfile /var/run/redis_6379.pid
# 改为
pidfile /var/run/redis_6380.pid

## 3. 修改日志地址文件名称
/logfile
# 将
logfile ""
# 改为
logfile "6380.log"

## 4. 修改数据库备份文件名称
/dbfile
# 将
dbfilename dump.rdb
# 改为
dbfilename dump6380.rdb

## *5. 如果要做为 master 的 Redis 设置过 auth(密码)
/masterauth
# 将
#masterauth <master-password>
# 的注释“#”去掉,改为
masterauth asdf		// “asdf”为将作为主 master 的数据库设置的密码

  • 启动两个服务器
# 删除原来的 Redis 进程
kill -9 $(pidof redis-server)

# 启动 6379 和 6380 两个服务器
/usr/local/redis/bin/redis-server  /usr/local/redis/etc/6379.conf
/usr/local/redis/bin/redis-server  /usr/local/redis/etc/6380.conf
ps aux | grep redis-server

# 分别进入(建议开两个终端)
/usr/local/redis/bin/redis-cli -p 6379
auth asdf	# 输入密码(如果有的话)

/usr/local/redis/bin/redis-cli -p 6380
auth asdf	# 输入密码(如果有的话)

# 查询两台服务器配置
info		// 返回
# Replication
role:master
connected_slaves:0
...

# 发现两台服务器的角色都是 master
# 把 6380 变为 slave,6379 保持 master
## 在 6380 终端输入:
slaveof 127.0.0.1 6379	// 返回 OK
info		// 返回
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
...

# 验证一下,在 6379 设置两个 key,看 6380 能否收的到
## 在 6379 终端输入:
set key1 zhangsan	// 返回 OK
set key2 lisi		// 返回 OK
get key1			// 返回 "zhangsan"
get key2			// 返回 "lisi"

## 在 6380 终端输入:
get key1			// 返回 "zhangsan"
get key2			// 返回 "lisi"

  • 到此,6379 和 6380 设置的主从关系设置完成
  • 但是这种方式只能保证建立临时的主从关系。一旦 master 服务器重启或者宕机之后,它们之间的主从关系立刻终止
  • 若想长期保持两台服务器之间的主从关系,那么我们需要在配置文件中做修改。
  • 这里需要说一下,主数据库不需要做任何配置。要修改只需要修改从数据库的配置文件。
# 进入到 Redis 配置文件所在文件夹
cd /usr/local/redis/etc

# 修改 slave 的配置文件
vim 6380.conf
/slaveof	// 搜索关键字,没有的话,Shift + G 移动到最后一行,添加一下代码:
slaveof 127.0.0.1 6379
# 保存后退出

1.6 主从复制常见问题
  • 当 6380 成为 6379 的从库之后,6380 是否能获取的到 6379 以前的数据库。答案是肯定的。因为每次简历主从复制之后,主机将传送整个数据库文件到从机。
  • 从库能不能写数据?在默认情况下,从库是只读的,在从库中写入数据将报错。但是也可以通过修改配置文件的方式允许从库写入数据。但是由于从库中修改的数据不会被同步到其它任何数据库,并且一旦主库修改了数据,从库的数据就会因为自动同步被覆盖,所以一般情况下不建议将从库设置为可写。
  • 主机宕机后,从机如何升级为主机以便快速恢复数据?可以通过两种方式来实现。
    • 第一种是人工手动修改的方式。从机可以运行命令 slaveof no one 来停止来自其他数据库的同步而升级为主机。但是这里要注意,当一个从库反客为主之后,别的从库都要运行一次 slaveof 反客为主机器的ip 端口号,要是从库数量比较多的话,会耗时同时增加错误量。那么有没有一种自动修改的模式呢?那就是哨兵模式
    • 哨兵模式,就是增加一个哨兵,随时巡视参加主从复制的服务器。通过以下步骤实现哨兵模式。
# 进入到 Redis 配置文件所在文件夹
cd /usr/local/redis/etc

# 创建配置文件(文件名字一定要叫“sentinel”)
vim sentinel.conf

# 写入以下内容
# 最后的 1 表示至少一个哨兵
sentinel monitor mymaster 127.0.0.1 6379 1
sentinel auth-pass mymaster asdf1

# 开启
/usr/local/redis/bin/redis-sentinel /usr/local/redis/etc/sentinel.conf

2. Redis 事务控制

2.1 什么是 Redis 事务控制
  • Redis 事务可以一次性执行多个命令,但是由于 Redis 只能保证一个客户端发起的事务命令可以连续执行,而中间不会插入其它客户端的命令。一般情况下,Redis 在接收一个客户端发来的命令后会立即处理,并返回处理的结果。
  • 但是在一个客户端在链接中发出 multi 命令时,就会进入一个事务,该链接后续的命令并不会立即被执行,而是先放到一个队列中。当此链接在接收到 exec 命令后,Redis 会顺序的执行队列里的所有命令,并将所有命令运行的结果打包到一起返回给客户端,然后就结束这个事务。
  • Redis 事务是一个单独的隔离的操作,事务中的所有命令都会序列化,按顺序的执行。同时事务中的命令要么全部被执行,要么全部都不执行。
2.2 事务控制常用的命令
序号命令解释
1discard取消事务,放弃执行事务块内的所有命令
2exec执行所有事务块内的命令
3multi标记一个事务块的开始
4watch监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断
5unwatch取消 watch 命令对所有 key 的监视
# 演示
## multi & exec
set age 20		// 返回 OK
set weight 75	// 返回 OK
set height 185	// 返回 OK
multi			// 返回 OK。(开始事务)
incr age		// 返回 QUEUED
incr weight		// 返回 QUEUED
incr height		// 返回 QUEUED
exec			// (执行事务里的命令)返回
1) (integer) 21
2) (integer) 76
3) (integer) 186

## discard
// 取消事务,放弃执行事务块内的所有命令
multi			// 返回 OK。(开始事务)
incr age		// 返回 QUEUED
incr weight		// 返回 QUEUED
discard			// 返回 OK
get age			// 返回 "21"
get height		// 返回 "186"

## watch
// 会监视给定的 key。
// 当 exec 的时候,如果监视的 key 在启用 watch 之后发生过变化,则整个事务就会失败
// 也可以调用 watch 监视多个 key,这样就可以对指定的 key 加乐观锁了
// watch 的 key 是对整个连接是有效的,事务也是一样
// 如果连接断开了,事务和 watch 就都会被清除。
// 当遇到 exec,discard 和 unwatch 命令,都会清除连接中的所有监视。

// 什么是“乐观锁”?“乐观锁”是相对于“悲观锁”而言的。
// 乐观锁假设认为数据在一般情况下不会造成冲突。
// 如果在数据进行提交更新的时候,才会正式对数据的冲突进行检测。
// 如果发现冲突了,则返回错误的信息。
// 乐观锁是如何实现的?
// 一般是使用数据版本记录机制来实现的,这是乐观锁最常用的一种实现方式。

// 什么是数据版本?数据版本就是为数据增加一个版本标识。
// 一般是通过为数据库表增加一个数字类型的 version 字段来实现的。
// 当读取数据的时候,将 version 字段值一起读出,如果数据每更新一次,version 值增加 1。
// 当提交更新的时候,判断数据库表对应记录的 version 值是否与提取出的 version 值相等。
// 如果相等,则予以更新。否则认为是过期的数据。

// 下面的例子是正确实现 incr 命令的例子:
set age 25		// 返回 OK
watch age		// 返回 OK
get age 		// 返回 "25"
multi			// 返回 OK
set age 50		// 返回 QUEUED
incr age		// 返回 QUEUED
exec			// 返回
1) OK
2) (integer) 51
get age 		// 返回 "51"

// 下面的例子是由于所监视的 key 被更改而事务命令没有被执行
// 进入终端 1:
watch age		// 返回 OK
set age 30		// 返回 OK
multi			// 返回 OK

// 进入终端 2:
set age 28		// 返回 OK

// 回到终端 1:
set age 50		// 返回 QUEUED
exec			// 返回 (nil),乐观锁认为 age 50 是过期数据,不被执行
get age			// 返回 "28"

## unwatch
// 取消 watch 命令对所有 key 的监视
// 进入终端 1:
watch age		// 返回 OK
get age			// 返回 "28"
unwatch			// 返回 OK
multi			// 返回 OK

// 进入终端 2:
set age 100		// 返回 OK

// 回到终端 1:
set age 50		// 返回 QUEUED
exec			// 返回 1) OK
get age 50		// 返回 "50"

  • 事务的全部执行和部分执行
    • Redis 事务实现是如此的简单,当然也会存在一些问题
    • Redis 只能保证事务的每个命令连续执行,但是如果事务中的一个命令失败了,会出现:
    • 事务中的命令在回车之后显示 “QUEUED”,就会全部被执行。虽然命令中可能会有错误,但是所有的命令会继续执行下去。但是显示 “ERROR”的话,则事务中的命令将全部不会被执行。
# 演示
set age 25		// 返回 OK
set name wdm	// 返回 OK
set weight 75	// 返回 OK
multi			// 返回 OK
incr age		// 返回 QUEUED
incr name		// 返回 QUEUED
incr weight		// 返回 QUEUED
exec			// 返回
1) (integer) 26
2) (error) ERR value is not an integer or out of range
3) (integer) 76
// 虽然 incr name 虽然失败,但是其它两条还是执行。
// 是因为三条命令都返回 QUEUED,所以命令全部执行

set age 30		// 返回 OK
set name wdm	// 返回 OK
set weight 80	// 返回 OK
multi			// 返回 OK
incr age		// 返回 QUEUED
incr weight		// 返回 QUEUED
getset name		// 返回 (error) ERR wrong number of arguments for 'getset' command
exec 			// 返回 (error) EXECABORT Transaction discarded because of previous errors.

3. Redis 持久化及操作

3.1 为什么做 Redis 持久化

由于 Redis 的数据都是存放在内存中的,如果没有持久化的配置,Redis 重启之后数据就全部丢失了。于是需要开启 Redis 的持久化功能,将数据保存到磁盘上。当 Redis 重启之后,可以从磁盘中恢复数据

3.2 Redis 持久化的方式有哪些

Redis 提供两种方式的持久化,RDB 持久化和 AOF 持久化。

3.3 RDB 持久化与 AOF 持久化的区别
  • RDB 持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘。实际操作是 folk (复制)一个子进程,再将数据集写入临时文件,写入成功之后再替换之前的文件,并用二进制进行压缩存储。
  • AOF 持久化是以日志的形式记录服务器所处理的每一个“写”和“删除”操作,查询操作不会被记录。AOF 持久化以文本的方式记录,可以将 AOF 持久化文件打开,查看详细的操作记录。
3.4 RDB 持久化与AOF 持久化的优缺点
  • RDB 持久化的优势

    • 一旦采用该方式,那么整个 Redis 数据库将只包含一个文件。通过不同的备份策略,来保证系统数据的安全。一旦系统出现灾难性的故障,可以非常容易的进行恢复。
    • 对于灾难恢复而言,RDB 是可以非常轻松的将一个单独文件压缩后再转移到其它介质上。
    • 性能的最大化。对于 Redis 的服务进程而言,在开始持久化的时候,它只需要做的是 folk 出子进程,之后在由子进程完成这些持久化的工作。这样就可以极大的实现性能的最大化。
    • 相比于 AOF 机制来说,如果数据集非常的大,RDB 的启用效率会更高一些。
  • RDB 持久化的劣势

    • 如果想保证数据的高可用性,即最大限度的避免数据的丢失,那么 RDB 将不会是一个很好的选择。
    • 因为系统一旦在定时持久化之前出现宕机现象,此前没有来得及写入磁盘的数据将会丢失。
    • 由于 RDB 是通过 folk 子程序来协助完成数据持久化工作的,因此如果当数据集比较大的时候,可能会导致整个整个服务器通知服务几百毫秒甚至是一秒钟的时间
  • AOF 持久化的优势

    • 可以带来更高的数据安全性,即数据的持久性。AOF 有三种同步机制:每秒钟同步、每修改同步、不同步三种同步策略。
      • 每秒钟同步也是异步完成的,其效率是非常高的。但是一旦系统出现宕机的现象,那么一秒钟之内修改的数据将会丢失。
      • 而每修改同步,即每次发生的数据变化都会被记录到磁盘中,这种方式在效率上是最低的。
    • 由于该机制对日志文件的写入操作采用的是 append模式,因此在写入过程中,即使出现宕机的现象,也不会破坏日志文件中已经存在的内容
    • 如果日志过大,Redis 可以自动启用重写机制
    • AOF 持久化的日志文件,相对来说,格式清晰,易于理解
  • AOF 持久化的劣势

    • 对于相同数量的数据集而言,AOF 持久化的文件通常要大于 RDB 持久化的文件。RDB 持久化策略在恢复大数据集的时候比 AOF持久化策略的恢复速度要快。
    • 根据同步策略的不同,AOF 持久化在运行效率上往往会慢于 RDB 持久化。
  • 对于 RDB 持久化和 AOF 持久化两者选择的标准,要根据实际的需求,看是愿意牺牲一些性能,换取更高的缓存一致性,还是愿意承担一定的风险,来换取更高的性能。

3.5 RDB 持久化与 AOF 持久化的配置
# RDB 持久化的配置
# RDB 持久化是记录一段时间内的操作
# 一般的配置是,一段时间内操作超过 n 次,就持久化

# 进入到 Redis 配置文件所在文件夹
cd /usr/local/redis/etc

# 修改配置文件
vim redis.conf
/save
save 900 1		//  在 900 秒后如果至少有 1 个 key 发生变化,则 dump 内存快照
save 300 10		//  在 300 秒后如果至少有 10 个 key 发生变化,则 dump 内存快照
save 60 10000	//  在 60 秒后如果至少有 10000 个 key 发生变化,则 dump 内存快照
# RDB 持久化这三种都收默认开启的,可以通过在 save 前面加上“#”的方式来禁用 RDB 持久化
# 若采用 RDB 持久化,还要采取以下的措施
## 1. 修改快照名称
/dbfile
# 将
dbfilename dump.rdb
# 改为
dbfilename dump_6379.rdb

## 2. 修改快照存放目录
# 将
dir ./
# 改为
dir /var/lib/redis/

# 保存退出

## 3. 创建快照存放目录
mkdir /var/lib/redis/

# AOF 持久化的配置
# 进入到 Redis 配置文件所在文件夹
cd /usr/local/redis/etc

# 修改配置文件
vim redis.conf

## 1. 开启 AOF
/appendonly
# 将
appendonly no
# 改为
appendonly yes

# 再往下看,将看到
# appendfsync always		// 每次写入 AOF
appendfsync everysec		// 每秒写入
# appendfsync no			// 不同步

# 这里不要修改,直接保存退出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值