Redis能保证ACID的哪些特性?

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
日志服务 SLS,月写入数据量 50GB 1个月
简介: Redis能保证ACID的哪些特性?

Redis能保证ACID的哪些特性?

文章目录

Redis事务ACID分析

总结:

原子性

  • 命令入队时就报错,会放弃事务执行,保证原子性;
  • 命令入队时没报错,实际执行时报错,不保证原子性;
  • EXEC 命令执行时实例故障,如果开启了 AOF 日志,可以保证原子性。

一致性:能保证一致性

隔离性:能保证隔离性

持久性:不能保证持久性

原子性(A)分析

如果命令正常运行,事务中的原子性是可以得到保证的。

那么在执行命令的过程中如果有命令失败了呢?

过程中执行命令失败很可以不会保证原子性操作,因为这是要分情况的。

1、命令入队就报错

比如执行一个不存在的命令,或者命令的写错了

例如下面代码:

127.0.0.1:6379> set test-mult-key 100
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> DECR test-mult-key
QUEUED
# DECR 命令拼写错了
127.0.0.1:6379> DECRR test-mult-key
(error) ERR unknown command `DECRR`, with args beginning with: `test-mult-key`,
127.0.0.1:6379> DECR test-mult-key
QUEUED
127.0.0.1:6379> EXEC
(error) EXECABORT Transaction discarded because of previous errors.

可以看到事务中 DECR 的命令拼写错了,写成了 DECRR。这时候事务是不能执行的,在执行 EXEC 的时候,Redis 抛出了错误,整个事务的执行被丢弃了。

对于这种情况,在命令入队时,Redis就会报错并且记录下这个错误。此时,我们还能继续提交命令操作。等到执行了EXEC命令之后,Redis就会拒绝执行所有提交的命令操作,返回事务失败的结果。这样一来,事务中的所有命令都不会再被执行了,保证了原子性。

2、命令执行的时候报错

这种情况,就是我们操作 Redis 命令时候,命令的类型不匹配。

栗如:我们对一个 value 为 string 类型的 key,执行 DECR 操作。

127.0.0.1:6379> set test-mult-key 100
OK
127.0.0.1:6379> set test-mult-key-string 's100'
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> DECR test-mult-key
QUEUED
127.0.0.1:6379> DECR test-mult-key
QUEUED
# 对 value 为 string 的,执行 DECR 操作,结果会报错
# 模拟错误的命令
127.0.0.1:6379> DECR test-mult-key-string
QUEUED
127.0.0.1:6379> DECR test-mult-key
QUEUED
127.0.0.1:6379> EXEC
1) (integer) 99
2) (integer) 98
3) (error) ERR value is not an integer or out of range
4) (integer) 97

这种情况下,虽然错误的命令会报错,但是还是会把正确的命令执行完成。

这种情况下,命令的原子性就无法得到保证了。Redis 中没有提供事务的回滚机制。

3、EXEC命令执行时实例发生故障

如果 Redis 开启了 AOF 日志,那么,只会有部分的事务操作被记录到 AOF 日志中。

机器实例恢复后,我们可以使用 redis-check-aof 工具检查 AOF 日志文件,这个工具可以把已完成的事务操作从 AOF 文件中去除。这样一来,我们使用 AOF 恢复实例后,事务操作不会再被执行,从而保证了原子性。

总结

所以关于 Redis 中事务原子性的总结,就是下面几点

  • 命令入队时就报错,会放弃事务执行,保证原子性;
  • 命令入队时没报错,实际执行时报错,不保证原子性;
  • EXEC 命令执行时实例故障,如果开启了 AOF 日志,可以保证原子性。

一致性(C)分析

关于一致性的分析还是从上面三个点来展开

1、命令入队时就报错

事务本身就不会执行,一致性可以得到保证

2、命令执行的时候报错

有错误的命令不会被执行,正确的命令可以正常执行,也不会改变数据库的一致性。

3、EXEC命令执行时实例发生故障

如果没有开启持久化,那么实例故障重启后,数据都没有了,数据库是一致的。

如果使用 RDB 快照,因为 RDB 快照不会在事务执行时执行,所以事务执行的结果不会保存到 RDB 快照中,使用 RDB 快照进行恢复时,数据库中的数据也是一致性的。

如果我们使用了 AOF 日志,而事务操作还没有被记录到 AOF 日志时,实例就发生了故障,那么,使用 AOF 日志恢复的数据库数据是一致的。如果只有部分操作被记录到了 AOF 日志,我们可以使用 redis-check-aof 清除事务中已经完成的操作,数据库恢复后也是一致的。

总结:Redis 中对于数据一致性属性还是有保证的。

隔离性(I)分析

事务的隔离性要求每个读写事务的对象对其他事务的操作对象相互分离,即该事务提交前对其他事务都不可见。

这里分析下 Redis 中事务的隔离性,Redis 中事务的隔离性将从下面两个方面进行分析

1、如果在命令入队,EXEC执行之前,有并发操作

因为 Redis 在事务提交之前只是把命令,放入到了队列中,所以如果在命令入队,EXEC执行之前,有并发操作,这种情况下,事务是没有隔离性的。

这种情况下,可以借助于 watch 实现:

1、客户端 1 首先,使用 watch 监听一个 key,然后开始一个事务,在事务中写入一些命令;

127.0.0.1:6379> set test-mult-key 100
OK
127.0.0.1:6379> watch test-mult-key
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> DECR test-mult-key
QUEUED
127.0.0.1:6379> DECR test-mult-key
QUEUED

2、客户端 2 在客户端 1 事务提交之前,操作修改该键值;

127.0.0.1:6379> DECR test-mult-key
(integer) 99

3、客户端 1 提交事务;

127.0.0.1:6379> EXEC
(nil)

从上面的结果可以看到如果使用 watch 之后,如果当前键值,在事务之外有了修改,那么当前事务就会放弃本次事务的执行。这样就实现了事务的隔离性。

1、如果在事务提交之后,有并发操作

这种情况下是没有问题的,Redis 会先把事务中的命令执行完成,然后再去执行后续的命令,因为 Redis 对于命令的执行是单线程的,这种情况下,可以保证事务的隔离性。

总结:事务的隔离性可以保证。

持久性(D)分析

Redis 是会存在丢数据的情况的,如果在数据持久化之前,数据库宕机,那么就会有一部分数据没有及时持久化,而丢失。

虽然他有RDB和AOF日志,但是要保证性能,所以不能保证真正的保存,所以可能存在一部分数据一部分数据没有及时持久化的情况

所以,Redis 中不能保证事务的持久性

Redis 为什么不支持回滚?源码分析

Redis 中为什么没有提供事务的回滚,有下面两个方面的考量

1、Redis是单线程的,支持回滚会对 Redis 的简单性和性能有很大的影响;

2、Redis 中只有在 语法错误者键值的类型操作错误 中才会出错,这些问题应该在开发中解决,不应该出现在生产中。

基于上面两点的考虑,目前 Redis 中不支持事务的回滚。


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
6月前
|
存储 缓存 NoSQL
聊聊 Redis 的高级特性之一: 发布订阅
Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。 图中,消费者1和消费者2 订阅了 Redis 服务的频道 channel ,当生产者通过 PUBLISH 命令发送给频道 channel 时, 这个消息就会被发送给订阅它的两个客户端。
聊聊 Redis 的高级特性之一: 发布订阅
|
22天前
|
存储 缓存 监控
利用 Redis 缓存特性避免缓存穿透的策略与方法
【10月更文挑战第23天】通过以上对利用 Redis 缓存特性避免缓存穿透的详细阐述,我们对这一策略有了更深入的理解。在实际应用中,我们需要根据具体情况灵活运用这些方法,并结合其他技术手段,共同保障系统的稳定和高效运行。同时,要不断关注 Redis 缓存特性的发展和变化,及时调整策略,以应对不断出现的新挑战。
56 10
|
1月前
|
存储 消息中间件 NoSQL
【redis】redis的特性和主要应用场景
【redis】redis的特性和主要应用场景
106 1
|
1月前
|
NoSQL 关系型数据库 MySQL
Redis 事务特性、原理、具体命令操作全方位诠释 —— 零基础可学习
本文全面阐述了Redis事务的特性、原理、具体命令操作,指出Redis事务具有原子性但不保证一致性、持久性和隔离性,并解释了Redis事务的适用场景和WATCH命令的乐观锁机制。
221 0
Redis 事务特性、原理、具体命令操作全方位诠释 —— 零基础可学习
|
4月前
|
消息中间件 缓存 NoSQL
Redis快速度特性及为什么支持多线程及应用场景
Redis快速度特性及为什么支持多线程及应用场景
111 11
|
3月前
|
NoSQL Java 调度
Lettuce的特性和内部实现问题之Redis的管道模式提升性能的问题如何解决
Lettuce的特性和内部实现问题之Redis的管道模式提升性能的问题如何解决
|
3月前
|
NoSQL 网络协议 安全
Lettuce的特性和内部实现问题之Lettuce天然地使用管道模式与Redis交互的问题如何解决
Lettuce的特性和内部实现问题之Lettuce天然地使用管道模式与Redis交互的问题如何解决
|
5月前
|
监控 NoSQL 网络安全
Redis 6和7:探索新版本中的新特性
Redis 6和7:探索新版本中的新特性
|
6月前
|
存储 NoSQL 关系型数据库
redis-学习笔记(概念, 相关名词, 特性, 优势: 快)
redis-学习笔记(概念, 相关名词, 特性, 优势: 快)
38 0
|
6月前
|
监控 NoSQL 关系型数据库
深入浅出Redis(五):Redis的事务机制与ACID原则
深入浅出Redis(五):Redis的事务机制与ACID原则