在某些情况下提升性能。利用事务一次性发送多个命令,然后等待所有回复出现实现流水线 (pipeline)。通过减少客户端与 Redis 服务器之间的网络通信次数来提升 Redis 在执行多个命令时的性能。
关系数据库事务与 Redis 事务的区别: P76
关系数据库:先向数据库服务器发送 BEGIN ,然后执行各个相互一致 (consistent) 的读写操作,最后可以选择发送 COMMIT 来确认之前的修改,或者发送 ROLLBACK 来放弃之前的修改。
Redis :以特殊命令 MULTI 开始,然后传入多个命令,最后以 EXEC 结束,并依次执行传入的命令。Redis 事务不能以一致的形式读取数据,使得某一类型的问题难以解决,且无法实现二阶段提交。
通过使用 WATCH, MULTI/EXEC, UNWATCH/DISCARD 等命令,程序可以在执行某些重要操作时,通过确保自己正在使用的数据没有发生变化来避免出错。 P78
WATCH: 使用 WATCh 对键进行监视之后,直到用户执行 EXEC 的这段时间里面,如果有其他客户端抢先对任何被监视的键进行了替换、更新或删除等操作,那么当用户尝试执行 EXEC 时,事务将失败并返回一个错误。(之后用户可选择重试事务或者放弃事务)
UNWATCH: 可以在 WATCH 执行之后、 MULTI 执行之前对连接进行重置 (reset)
DISCARD: 可以在 MULTI 执行之后、 EXEC 执行之前对连接进行重置,即取消 WATCH 并清空所有已入队命令
为什么 Redis 没有实现典型的加锁功能? P82
加锁是悲观锁,持有锁的客户端运行越慢,等待解锁的客户端被阻塞的时间越长
WATCH 是乐观锁,客户端不必等待取得锁,只需要在事务执行失败时重试即可,乐观锁可以提高并发能力
非事务型流水线 (non-transactional pipeline)对于无需事务的大量操作可以使用非事务型流水线,可以避免事务消耗资源。
Python 中通过修改入参即可将事务改为非事务型流水线,而 Go 中根据具体框架的不同,可能需要手动封装流水线的处理逻辑。
性能优化要对 Redis 的性能进行优化,首先需要弄清楚各种类型的 Redis 命令能跑多块,而这一点可以通过调用 Redis 附带的性能测试程序 redis-benchmark 得知。 P85
切记不要将输出结果看作是应用程序的实际性能,因为 redis-benchmark 不会处理执行命令所获得的命令回复,所以它节约了大量用于对命令回复进行语法分析的时间。 P86
可能影响性能的原因 P86未使用流水线:可视情况适当使用流水线
对于每个命令或每组命令都创建了新的连接:使用连接池重用 Redis 连接
Redis 的数据结构或命令不合理(value 非常大,使用 keys, hgetall 等):优化数据结构和命令
本文首发于公众号:满赋诸机(点击查看原文) 开源在 GitHub :reading-notes/redis-in-action