StackExchange.Redis 系列 3:Pipelines and Multiplexers 说明
本系列博文是“伪”官方文档翻译,并非完全将官方文档进行翻译,而是我在查阅、测试原始文档并转换为自己东西后进行的“准”翻译。
本系列本博文基于 redis 5.0.6,系列中部分博文跟官方文档有出入,有不同见解 / 说明不当的地方,还请大家不吝拍砖。
Pipeline
-
在使用 Redis 的时候,大部分的耗时会集中在网络延时上,通过 Pipeline,可以把多次网络请求合并为 1 次,提高性能。
当你执行如下同步方法的时候:
1 | string a = db.StringGet("a"); |
-
只有等你得到了 a 的值以后,获取 b 的值的请求才会发出去。
通过 Pipeline 机制,可以让你不需要等待前一次请求的结果后再进行请求。
-
.NET 下,通过 TPL(Tasl/Task
) 来实现 Pipeline 效果,如下:
1 | var aPending = db.StringGetAsync("a"); |
时序图:
Multiplexing
有的时候我们会存在这样的业务场景:获取 a 的值,根据 a 的结果值再从 redis 服务器上获取 b,对于 Redis 原生命令而言,可以通过 BLPOP,PRPOP,PRPOPLPUSH 之类的命令来实现,但对于 StackExchange.Redis 而言,StackExchange官方并未提供这些原生命令特性,因为这些命令会阻塞整个线程。
鉴于此,StackExchange.Redis 在单个连接上可以达到极高的吞吐量。
如果你想要 BLPOP 这样的命令,可以通过 ”发布/订阅“的方式来变相实现,方式如下:
1 | sub.Subscribe(channel, delegate { |
-
通过这种方式可以实现无阻塞的效果。
- 数据不是通过 pub/sub 来发送的,pub/sub API 只是用来通知 worker 去检查工作队列。
- 如果没有 worker,则新项将会保持再缓冲列表中。
- 只有 worker 可以 pop 值,当消费者数量大于生产者数量的时候,部分消费者虽然会被通知到,但什么事都不会去执行。
- 当你重启一个 worker 的时候,应假设存在工作项以便可以让你处理挤压项。
- 除上述外,语义和 BLPOP 相同。无论是同步请求还是异步请求,这些请求都会通过 Pipeline 进行
当不同的调用者同时使用它时,它会自动对单独的请求进行管道传输,因此,无论请求使用阻塞访问还是异步访问,工作都将通过管道进行。