写点什么

Redis 如何应对并发访问

用户头像
escray
关注
发布于: 2021 年 03 月 31 日
Redis 如何应对并发访问

Redis 如何应对并发访问?两种方式:原子操作和分布式锁。极客时间《Redis 核心技术与实战》专栏学习笔记 13,部分已经作为留言发布,但是留言太多,排在后面的一般很难被大家看到,所以集中发布在这里,欢迎讨论。


题图来自《基于 Redis 的分布式锁到底安全吗》,推荐观看

29 | 无锁的原子操作:Redis 如何应对并发访问?


Redis 同样会遇到并发访问问题,为了保证并发访问,Redis 提供了加锁和原子操作两种方式。


其实原子操作听上去比较高端,但实际上就是让多个操作变成一步,和事务有点像。加一减一这种比较简单的,Redis 自身就提供了 INCR/DECR 的命令;对于复杂多步骤的,可以编写 Lua 脚本,而 Redis 把 Lua 脚本当做“一条”命令来处理。


当然,如果 Lua 脚本内的操作过于复杂,耗时过长,Redis 的性能也会受到影响。


我觉的 Redis 从一出生,就是当做缓存来设计的,最好只做简单的读写操作(要是用作只读缓存就更合适了)。


对于课后题,读取客户端 ip 的访问次数,不需要添加到 Lua 脚本里面。假设有多个并发访问,获取到了当前的 ip 访问次数,假设不超过 20 且不为 NULL 值,那么每次(并发)访问,都给访问次数加一,这个没有问题。如果 value == 1,那么就设置过期时间,如果哪一个并发访问到了,都可以执行。


唯一可能有问题的地方,就是有超过 20 个并发同时访问到了 GET(ip),并且得到的值小于 20,然后都执行了加一操作,那么就会超过 20 的访问次数限制。

30 | 如何使用 Redis 实现分布式锁?


看完本文,觉得 Redis 其实挺适合用来设置分布式锁的,主要就是因为 Redis 的读写比较快。


单个 Redis 实例使用 SETNX 配合过期时间加锁,使用 Lua 脚本解锁,应该就能满足普通应用的需要了。


而 RedLock 其实是在单实例 Redis 锁的基础上,增加了半数以上的限制,有点 quorum 的意思。


对于课后题,我觉的应该是不行的。


一方面,对于 SETNX 的返回值没有判断,如果加锁 SETNX 就失败了怎么处理?


另一方面,过期时间设置为 10s 未必合适,一般来说可能是过长了,也可能太短。


看完课代表的答案,我知道自己又想歪了。课后题中的加锁代码,主要的问题在于不是原子的,如果客户端执行完 SETNX 后崩溃了,就没有机会执行 EXPIRE 了。


顺着课代表给出的链接,看了《基于Redis的分布式锁到底安全吗》,其中的分析确实精彩,而且还给出了不少有价值的链接,如果以后有机会做分布式的工作,应该会来重读。其中,走马观花了一下 Martin Kleppmann 和 antirez 之间(也包括其他分布式系统专家)对于 Redis 分布式锁安全性问题争论和探讨,感觉像是在看武林高手对决,当然胜负并不重要。


发布于: 2021 年 03 月 31 日阅读数: 12
用户头像

escray

关注

Let's Go 2017.11.19 加入

在学 Elasticsearch 的项目经理

评论

发布
暂无评论
Redis 如何应对并发访问