关于 Redis 队列的一道面试题

2016-03-08 15:01:55 +08:00
 tanteng

面试的时候讲到自己做的一个项目,我说用了 Redis 队列, lpush 进, rpop 出,面试官打断问:一般入队列没有问题,如果出对列阻塞了怎么办?实际生产环境中在这里没有出现问题,而且队列量很大,我没有太理解面试官问的什么。

Redis 作队列需要注意什么问题?如果是高并发情况下怎么办?谢谢大家指点!

30384 次点击
所在节点    Redis
38 条回复
Lucups
2016-03-08 17:35:22 +08:00
首先, Redis 是支持持久化的,所以队列数据完全可以持久化;其次, Consumer(Worker) 消化不了扛不住,先尝试多开一些,如果还不行,说明硬件或其他地方(如数据库存储)存在瓶颈,跟队列本身有毛关系?真以为上 Kafka 就能解决问题了?感觉题主没有 Get 到要点。
keakon
2016-03-08 17:37:50 +08:00
其实是让你用 epoll 之类的注册事件,等到可读时再去读…
hxsf
2016-03-08 17:48:45 +08:00
@tanteng redis 单线程,不存在并发读写,总会有个先来后到的。
hxsf
2016-03-08 17:54:32 +08:00
@keakon 直接 BRPOP 不就好了,读不到就阻塞,直到读到了再返回。
wikimore
2016-03-08 18:00:27 +08:00
BRPOP 一个时间周期(如阻塞 30 秒)轮询,不能一直阻塞,因为长时间连接没有读写可能会被系统干掉,作为客户端就永远阻塞在那里了,而同时服务端的队列里可能有很多消息了。
500miles
2016-03-08 18:00:44 +08:00
按我的理解, 是说 " consumer 吞吐量太弱, 不及 producer 生产速度, 此时何解? "

这就难玩儿了. . 就好比要解决北上广住房问题 .


不考虑移民 (投靠其他技术选型),

1. 监控队列, 动态调配 consumer, 适时增加 consumer

最简单有效的办法, 从根本上解决问题. 当然你得花钱加机器

2. 做好降级方案, 达到预设阀值, 出队后暂不处理, 直接先持久化再说


3. consumer 投递异步任务, 不要阻塞出队列

这个比较难玩儿
wikimore
2016-03-08 18:07:37 +08:00
redis 做队列主要问题应该就是内存,如果使用到 swap 的话, redis 的队列会异常的慢,还有就是消息的大小,不要超过 1K ,再大写入基本就是很慢了,还有就是主从保证高可用,如果量非常大,可以多实例做 partition ,不过这时候用 Kafka 明显更划算, Redis 做做小业务玩玩还是可以的。
bengol
2016-03-08 18:12:11 +08:00
允许请求超时 /失败,做好失败后处理
imlewc
2016-03-08 18:28:01 +08:00
分布式 一键解决
keakon
2016-03-08 19:00:38 +08:00
@hxsf 你的服务有 10 万并发时,第一个堵塞了,后面的都傻眼?
isno
2016-03-08 19:24:23 +08:00
涉及队列的任务学会先消费后处理
CosWind
2016-03-08 19:45:45 +08:00
@tanteng 还是不要用 redis 吧,我们用的是 rabbitmq
22too
2016-03-08 19:52:57 +08:00
我们也是 rabbitmq
hxsf
2016-03-08 20:42:46 +08:00
@keakon 读不到才阻塞(阻塞消费者),后面的消费者也会一起排队,有内容的时候按先后顺序解除阻塞啊。
redis 文档上的啊,做队列用的时候建议使用 R

官网文档 http://redis.io/commands/brpop

以下引用他人翻译的

列表的阻塞操作 (blocking)
列表有一个特别的特性使得其适合实现队列,通常作为进程间通信系统的积木:阻塞操作。

假设你想往一个进程的列表中添加项,用另一个进程来处理这些项。这就是通常的生产者消费者模式,可以使用以下简单方式实现:

生产者调用 LPUSH 添加项到列表中。
消费者调用 RPOP 从列表提取 / 处理项。
然而有时候列表是空的,没有需要处理的, RPOP 就返回 NULL 。所以消费者被强制等待一段时间并重试 RPOP 命令。这称为轮询(polling),由于其具有一些缺点,所以不合适在这种情况下:

强制 Redis 和客户端处理无用的命令 (当列表为空时的所有请求都没有执行实际的工作,只会返回 NULL)。
由于工作者受到一个 NULL 后会等待一段时间,这会延迟对项的处理。
于是 Redis 实现了 BRPOP 和 BLPOP 两个命令,它们是当列表为空时 RPOP 和 LPOP 的会阻塞版本:仅当一个新元素被添加到列表时,或者到达了用户的指定超时时间,才返回给调用者。
moe3000
2016-03-08 21:04:38 +08:00
1 、 brpop 可以解决
2 、 redis 分布式部署?具体没研究过。。
keakon
2016-03-09 02:22:12 +08:00
@hxsf 我觉得我已经说得够清楚了,你实际去做的话,就知道面试官为什么会这样问了…
solaro
2016-03-09 11:12:14 +08:00
@wikimore 咦,才 1K ,我之前做的都是限制 10K 以内, 5000/S 的吞吐量还是很快的。大促高峰期内存各种报警
jinya
2018-03-17 13:20:35 +08:00
马克

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/261936

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX