在这个page listing the redis clients中,我计算了8个异步库。我的理解是,当异步回调函数没有为I / O互相争斗时,像node.js或tornado这样的框架才有意义,否则你也可以同步。
但Redis是单线程的。所以他们实际上在为I / O而战。 Redis的单线程特性是否取消了异步回调的所有潜在优势?为什么在Redis中使用异步客户端是有意义的?
答案 0 :(得分:10)
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引擎的基石之一。