为什么为Redis使用异步客户端是有意义的?

usu*_* me 4 asynchronous tornado reactor redis node.js

列出redis客户端的这个页面中,我计算了8个异步库.我的理解是,当异步回调函数没有为I/O互相争斗时,像node.js或tornado这样的框架才有意义,否则你也可以同步.

但是Redis是单线程的.所以他们实际上在为I/O而战.Redis的单线程特性是否取消了异步回调的所有潜在好处?为什么在Redis中使用异步客户端是有意义的?

Did*_*zia 11

Redis的单线程特性与异步客户端的潜在优势无关.尽管Redis具有独特的事件循环,但它能够同时管理大量客户端连接.我在单个Redis实例上看到了最多30000个连接的基准测试.

考虑到内存键/值存储(如Redis或memcached),性能和延迟主要由网络往返而不是服务器端CPU消耗决定.当然,当网络链路饱和时,网络往返的延迟会增加,但并不意味着当网络远离饱和时它会变得微不足道.例如,在负载非常轻的1 GbE网络上,看到RTT延迟接近200 us并不罕见.

结果是,除非网络链接接近饱和,否则客户端连接(或异步回调函数)很少相互竞争I/O. 套接字与缓冲区相关联,可以分摊网络上读写操作的成本.大多数情况下,等待状态不是由于I/O竞争,而是由于网络的延迟.

有多种方法可以减少网络延迟的影响:

  • 流水线操作:将多个命令组合在一起,以便每组命令支付一次网络往返(实际上,这是同步流水线操作).

  • 非阻塞I/O:虽然它不会减少往返次数(或它们的单独成本),但异步客户端可以同时管理它们.结果是网络延迟对应用程序吞吐量的影响较小(或没有).

  • 多个客户端连接:每个客户端连接都有自己的套接字,因此也有自己的缓冲区.更多缓冲通常意味着更好的吞吐 更多的连接增加了同时和/或异步处理事物的机会,对整体性能产生了积极影响.

Redis生态系统支持这些解决方案,可以将这些解决方案结合起来以最大限度地提高性能.异步客户端通常允许这种组合.异步客户端的用例是什么?这里有一些例子:

  • 实现异步流水线操作,以最小化单个连接上的等待状态.

  • 将Redis连接与现有的事件循环(例如libevent,Node.js,Tornado,Twisted等等)集成,而不依赖于额外的线程池.

  • 支持使用多个Redis实例进行数据分片.在这种情况下,客户端应用程序可能希望并行化对各种实例的访问.使用异步客户端,可以通过唯一的线程方便地完成.

  • 基于客户端应用程序与各种主/从实例的预连接来支持HA弹性模型.

事件循环,异步库和/或类似协程机制是大多数高效NoSQL引擎的基石之一.