Redis 03
1 Redis事务
Redis通过 multi
、exec
、watch
等命令实现事务功能。Redis的事务功能相对较弱,无法和关系型数据库的事务相媲美。
1.1 multi 和 exec命令
语法:
multi 开始事务
命令1
命令2
...
exec 执行事务
示例:
127.0.0.1:6379> multi //开始事务
OK
127.0.0.1:6379> set age 18
QUEUED //事务中的命令并不会立刻执行,没有返回结果而是一个QUEUED(队列)
127.0.0.1:6379> getttt //故意执行一个不存在的命令,使得事务出错
(error) ERR unknown command 'getttt'
127.0.0.1:6379> set sex F //在错误命令后,再执行一个命令
QUEUED
127.0.0.1:6379> exec //执行事务,事务失败
(error) EXECABORT Transaction discarded because of previous errors.
//事务中,错误命令前和后的正确命令都没有执行
127.0.0.1:6379> get age
(nil)
127.0.0.1:6379> get sex
(nil)
1.2 watch命令
watch
命令用在 multi
命令前,用于监控任意数量的键是否发生改变。当执行 exec
命令时,将检查监视的键是否已经被修改,如果已经修改,服务器将拒绝执行事务。
语法:
watch 键
multi 开始事务
命令1
命令2
...
exec 执行事务 如果发现watch的键在事务执行前发生改变,则拒绝执行事务
示例:
![image-20200927160759572](Redis day03.assets/image-20200927160759572.png)
1.3 Redis事务的实现原理
Redis通过一个事务队列完成事务功能。
- 当一个客户端发送
multi
命令后,Redis服务器会将该客户端后续的命令保存到一个队列中。 - 当一个处于事务状态的客户端向Redis服务器发送
exec
命令时,服务器会遍历这个客户端的事务队列,执行队列中保存的所有命令,最后将执行命令的结果全部返回到客户端。 - Redis在执行事务队列的命令前,如果发现入队的命令有语法错误,或者监控的值发生改变,将清空队列中的命令,拒绝执行。
![image-20200927175238665](Redis day03.assets/image-20200927175238665.png)
1.4 Redis的弱事务性
在传统的关系型数据库中,常常使用A(原子性Atomicity)C(一致性Consistency)I(隔离性Isolation)D(持久性Durability)性质来检验事务功能的可靠性和安全性。而Redis的事务是不满足ACID特性的。
127.0.0.1:6379> set msg 'hello redis' //添加一个String数据
OK
127.0.0.1:6379> multi //开始事务
OK
127.0.0.1:6379> set name xiaohei
QUEUED
127.0.0.1:6379> rpush msg 1 2 3 //错误的使用rpush命令添加数据
QUEUED
127.0.0.1:6379> set age 18
QUEUED
127.0.0.1:6379> exec //运行时出现错误,并不会影响其它的命令
1) OK
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
3) OK
127.0.0.1:6379> get name
"xiaohei"
127.0.0.1:6379> get age
"18"
通过上述案例,可以看到redis事务并不能保证事务中的命令要么同时成功,要么同时失败。并且出现运行错误后,也无法回滚事务。
为什么Redis没有实现标准的事务?
- 会引入额外的复杂性,降低Redis的性能
- 没有必要引入,Redis适用的功能场景比较简单,使用Redis事务已经足够完成功能。
2 Redis的持久化机制
Redis的数据全部在内存中,如果突然宕机,内存中数据就会丢失,因此必须有一种机制来保证 Redis 的数据不会因为故障而丢失,这种机制就是Redis的持久化机制。
Redis有2种持久化机制:RDB(快照)机制 和 AOF(日志)机制
2.1 RDB(快照)机制
RDB机制保存的是数据,将内存中的数据写入磁盘永久保存,这是redis默认的机制。
原理:
- redis进程会创建一个子线程
- redis主线程继续处理客户端请求
- 子线程负责将子进程创建前的内存数据(快照数据)写入磁盘中名为dump.rdb文件
持久化时机:
- redis.conf配置文件中配置的有持久化时机
#在900秒(15分钟)之后,有大于等于1个key发生变化,则保存快照。
save 900 1
#在300秒(5分钟)之后,有大于等于10个key发生变化,则保存快照。
save 300 10
#在60秒(1分钟)之后,有大于等于10000个key发生变化,则保存快照。
save 60 10000
- 手动执行命令
bgsave
RDB的特点:
优势:
- 方便备份,很容易将一个rdb文件移动到其它机器上
- rdb在恢复大数据集时比aof速度要快
- rdb快照保存时,不影响主进程的工作
劣势:
- rdb每次要保存内存中所有数据,一般耗时较久。一旦宕机可能会丢失数据
- rdb机制下如果内存中数据量非常大,创建子进程会非常耗时
2.2 AOF(日志)机制
AOF(Append Only File)机制保存的是redis执行过的命令。
原理:
将redis执行过的每一个写命令都追加到日志文件(appendonly.aof)中。
当redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。
开启AOF机制
在配置文件中将 appendonly no 改为 appendonly yes
AOF机制开启之后,RDB机制和AOF机制同时运行
AOF持久化时机
配置文件中配置:
# appendfsync always //每次收到写命令就立即强制写入磁盘,最慢的,但是保证完全的持久化,不推荐使用 appendfsync everysec //每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,推荐 # appendfsync no //完全依赖os,性能最好,持久化没保证
AOF的特点
优势:
- AOF可以更好的保护数据不丢失
- AOF日志文件以append-only模式写入,写入性能比较高
- AOF日志可读性好,即使误删除了所有数据,只需要将日志中的删除命令去除,然后就可以根据日志恢复数据
劣势:
- 相同的数据集下,AOF文件通常大于RDB文件
- 如果持久化时机策略选择不合理,性能会非常差
- AOF在特殊情况下会出现一些bug
实战策略:
综合使用AOF和RDB两种持久化机制,用AOF来保证数据不丢失,作为数据恢复的第一选择;
用RDB来做不同程度的冷备,在AOF文件都丢失或损坏不可用的时候,还可以使用RDB来进行快速的数据恢复;
3 Redis的主从复制
3.1 主从复制引言
实际生产环境下,单机的redis服务器是无法满足实际的生产需求的。
第一,单机的redis服务器很容易发生单点故障,即使redis提供了各种持久化的方法来避免数据的丢失,但是物理上的故障(硬盘损毁等)还是无法完全避免的。
第二,如果对单台机器的性能进行纵向拓展,无论是CPU,内存还是磁盘容量都很容易达到瓶颈,无法满足实际需求。
针对这些问题,redis提供了**复制(replication)**的功能,通过"主从(一主多从)"和"集群(多主多从)"的方式对redis的服务进行水平扩展,用多台redis服务器共同构建一个高可用的redis服务系统。
3.2 搭建步骤
在Redis的主从模型下,主服务器既可以读也可以写,而从服务器原则上只允许读操作。接下来我们讲解一下主从复制的搭建。
-
克隆2台Redis机器,并编辑redis.conf
2台机器都要编辑绑定ip地址 bind 本机ip地址
-
主机正常启动,并关闭防火墙,关闭selinux
setenforce 0 systemctl stop firewalld redis-server /etc/redis/redis.conf
-
配置从机,编辑redis.conf
在 port 6379 后添加如下配置 slaveof 主机ip redis端口号,示例如下: slaveof 192.168.132.107 6379
-
启动从机
redis-server /etc/redis/redis.conf
-
最后可以通过命令查看主从关系
redis-cli -h 192.168.132.107 -p 6380 //登录到107这台电脑的6380这个redis里面。 info replication //查看主从关系
4 Redis的哨兵模式
4.1 哨兵模式引言
主从复制解决了数据备份的问题,但是如果主节点宕机,仍需要运维手动进行主从切换。要在主从复制下实现故障恢复的自动化,就需要使用Redis的哨兵(Sentinel)模式。
哨兵是一个独立于数据服务器的进程,用于监控redis数据服务器的状态,当主从模式下最关键的主服务器出现故障时,能够被哨兵自动的察觉。同时哨兵会在剩余的从服务器中**"选举"**出新的主服务器,达到自动化恢复系统服务的目的。
![image-20201016105345762](Redis day03.assets/image-20201016105345762.png)
哨兵本身也要考虑单点故障的问题,所以Redis Sentinel一般由3~5个节点组成,这样即使挂了个别哨兵节点,哨兵整体还可以正常工作。
客户端来连接集群时,会首先连接 sentinel,通过 sentinel 来查询主节点的地址,然后再去连接主节点进行数据交互。当主节点发生故障时,客户端会重新向 sentinel 要地址,sentinel 会将最新的主节点地址告诉客户端。如此应用程序将无需重启即可自动完成节点切换。
通过如下2图,演示故障切换的过程:![image-20201016110309620](Redis day03.assets/image-20201016110309620.png)
从上图可以看到主节点挂掉了,原先的主从复制也断开了,客户端和损坏的主节点也断开了。从节点被提升为新的主节点,其它从节点开始和新的主节点建立复制关系。客户端通过新的主节点继续进行交互。
![image-20201016110323109](Redis day03.assets/image-20201016110323109.png)
Sentinel 会持续监控已经挂掉了主节点。待它恢复后,原先挂掉的主节点现在变成了从节点,从新的主节点那里建立复制关系。
4.2 哨兵模式搭建
配置3个Redis(1主2从),3个哨兵
-
配置主从复制
-
配置哨兵
哨兵1配置sentinel.conf:
sentinel monitor mymaster 127.0.0.1 6379 2 修改为 sentinel monitor 主节点名 主节点ip 端口号 2 比如: bind 127.0.0.1 192.168.146.27 sentinel monitor mymaster 192.168.146.23 6379 2
哨兵2配置sentinel.conf:
bind 127.0.0.1 192.168.146.27
sentinel monitor mymaster 192.168.146.23 6379 2
哨兵3配置sentinel.conf:
bind 127.0.0.1 192.168.146.28
sentinel monitor mymaster 192.168.146.23 6379 2
重复执行redis-sentinel /etc/redis/sentinel.conf 启动3个哨兵。
4.3 哨兵的Spring Boot配置
application.yml 只配置哨兵节点
spring:
redis:
lettuce:
pool:
max-active: 500
max-idle: 50
min-idle: 10
max-wait: 30000
sentinel:
master: mymaster
nodes: 192.168.146.26:26379,192.168.146.27:26379,192.168.146.28:26379
标签:事务,127.0,持久,0.1,Redis,redis,6379,化机制
From: https://blog.51cto.com/sekior/6668927