在上一篇文章中,我们已经对 Redis 有了初步的认识,了解到 Redis 采用 Key-Value 的方式进行存储,在 Redis 内部,使用的是 redisObject 对象来表示所有的 key 和 value。同时我们还了解到 Redis 本身用的是单线程的机制,采用了多路 I/O 复用的技术,在处理多个 I/O 请求的时候效率很高。
今天我们来更加深入地了解一下 Redis 的原理,内容包括以下几方面:
- Redis 的事务处理机制是怎样的?与 RDBMS 有何不同?
- Redis 的事务处理的命令都有哪些?如何使用它们完成事务操作?
- 如何使用 Python 的多线程机制和 Redis 的事务命令模拟多用户抢票?
Redis 的事务处理机制
在此之前,让我们先来回忆下 RDBMS 中事务满足的 4 个特性 ACID,它们分别代表原子性、一致性、隔离性和持久性。
Redis 的事务处理与 RDBMS 的事务有一些不同。
首先 Redis 不支持事务的回滚机制(Rollback),这也就意味着当事务发生了错误(只要不是语法错误),整个事务依然会继续执行下去,直到事务队列中所有命令都执行完毕。在Redis 官方文档中说明了为什么 Redis 不支持事务回滚。
只有当编程语法错误的时候,Redis 命令执行才会失败。这种错误通常出现在开发环境中,而很少出现在生产环境中,没有必要开发事务回滚功能。
另外,Redis 是内存数据库,与基于文件的 RDBMS 不同,通常只进行内存计算和操作,无法保证持久性。不过 Redis 也提供了两种持久化的模式,分别是 RDB 和 AOF 模式。
RDB(Redis DataBase)持久化可以把当前进程的数据生成快照保存到磁盘上,触发 RDB 持久化的方式分为手动触发和自动触发。因为持久化操作与命令操作不是同步进行的,所以无法保证事务的持久性。
AOF(Append Only File)持久化采用日志的形式记录每个写操作,弥补了 RDB 在数据一致性上的不足,但是采用 AOF 模式,就意味着每条执行命令都需要写入文件中,会大大降低 Redis 的访问性能。启用 AOF 模式需要手动开启,有 3 种不同的配置方式,默认为 everysec,也就是每秒钟同步一次。其次还有 always 和 no 模式,分别代表只要有数据发生修改就会写入 AOF 文件,以及由操作系统决定什么时候记录到 AOF 文件中。
虽然 Redis 提供了两种持久化的机制,但是作为内存数据库,持久性并不是它的擅长。
Redis 是单线程程序,在事务执行时不会中断事务,其他客户端提交的各种操作都无法执行,因此你可以理解为 Redis 的事务处理是串行化的方式,总是具有隔离性的。
Redis 的事务处理命令
了解了 Redis 的事务处理机制之后,我们来看下 Redis 的事务处理都包括哪些命令。
- MULTI:开启一个事务;
- EXEC:事务执行,将一次性执行事务内的所有命令;
- DISCARD:取消事务;
- WATCH:监视一个或多个键,如果事务执行前某个键发生了改动,那么事务也会被打断;
- UNWATCH: