首页 文章

连接到redis时,Unix套接字比tcp慢

提问于
浏览
7

我正在开发高性能的Web服务器,它应该能够处理大约2k的同时连接和40k QPS,从而实现<7ms的resp时间 .

它的作用是查询Redis服务器(在同一主机上运行)并将响应返回给客户端 . 在测试期间,我观察到使用TCP STREAM_SOCKETs的实现比连接unix套接字更好 . 有大约1500个连接,TCP保持大约8ms,而unix套接字大约为50 .

服务器是用C语言编写的,它基于常量Posix线程池,我使用阻塞连接到Redis . 我的操作系统是CentOS 6,使用Jmeter,wrk和ab进行测试 . 为了与redis连接,我使用了 hiredis lib,它提供了这两种连接Redis的方法 .
据我所知,unix socket应该至少和TCP一样快 .

有人知道可能导致这种行为的原因是什么吗? . 我被卡住了 . 谢谢 .

2 回答

  • 1

    Unix域套接字通常比环回接口上的TCP套接字快 . 通常,Unix域套接字的延迟平均为2微秒,而TCP套接字则为6微秒 .

    如果我使用默认值(没有管道)运行redis-benchmark,我会看到每秒160k的请求,主要是因为单线程redis服务器受TCP套接字限制,160k请求以6微秒的平均响应时间运行 .

    使用Unix域套接字时,Redos每秒可实现320k SET / GET请求 .

    但是有一个限制,实际上我们在Torusware上已经达到了我们的产品Speedus,这是一个高性能的TCP套接字实现,平均延迟为200纳秒(请发送电子邮件至info@torusware.com申请Extreme Performance版本) . 延迟几乎为零,我们看到redis-benchmark每秒可实现约500k个请求 . 所以我们可以说redis-server延迟平均每个请求大约2微秒 .

    如果您想尽快回答并且您的负载低于redis-server峰值性能,那么避免流水线操作可能是最佳选择 . 但是,如果您希望能够处理更高的吞吐量,那么您可以处理请求的管道 . 响应可能需要更长时间,但您可以在某些硬件上处理更多请求 .

    因此,在前一个场景中,使用32个请求的管道(在通过套接字发送实际请求之前缓冲32个请求),您可以通过环回接口每秒处理多达100万个请求 . 在这种情况下,UDS的优势并不高,特别是因为处理此类流水线操作是性能瓶颈 . 实际上,管道为32的1M请求每秒大约有31k“实际”请求,我们已经看到redis-server每秒能够处理160k个请求 .

    Unix Domain Sockets分别处理大约每秒1.1M和1.7M的SET / GET请求 . TCP环回每秒处理1M和1.5个SET / GET请求 .

    通过流水线操作,瓶颈从传输协议转移到管道处理 .

    这与redis-benchmark网站中提到的信息一致 .

    但是,流水线操作会大大增加响应时间 . 因此,没有流水线操作,100%的操作通常在不到1毫秒的时间内运行 . 当流水线操作32请求时,高性能服务器中的最大响应时间为4毫秒,而如果redis-server在不同的计算机或虚拟机中运行,则最长响应时间为几十毫秒 .

    因此,您必须权衡响应时间和最大吞吐量 .

  • 18

    虽然这是一个老问题,但我想补充一下 . 其他答案谈论500k甚至1.7M响应/秒 . 这可以通过Redis实现,但问题是:

    客户端 - #Network# - > Webserver - #Something# - > Redis

    Web服务器的功能类似于我认为的Redis的HTML代理 .

    这意味着您的请求数量也仅限于Web服务器可以实现的请求数量 . 有一个经常被遗忘的限制:如果你有一个100Mbit连接,你可以使用每秒100.000.000位,但默认包装为1518位(包括包后的所需空间) . 这意味着:65k网络包 . 假设您的所有响应都较小,则由于CRC错误或丢失包而不得重新发送此类数据包的数据部分 .

    此外,如果未使用持久连接,则需要为每个连接执行TCP / IP握手 . 每个请求添加3个包(2个接收,一个发送) . 因此,在未经优化的情况下,您仍然可以向您的网络服务器提供21k可获得的请求 . (或者,对于'完美的'千兆位连接,为210k) - 如果您的响应适合一个175字节的数据包 .

    所以:

    • 持久连接只需要一点内存,因此启用它 . 它可以使您的表现翻两番 . (最好的情况)

    • 如果需要,可以使用gzip / deflate减小响应大小,以便它们尽可能少地包含在数据包中 . (丢失的每个数据包都可能丢失响应)

    • 通过剥离不需要的'garbage'减少响应大小像调试数据或长xml标签 .

    • HTTPS连接将增加一个巨大的(在这里进行比较)开销

    • 添加网卡并将其中继

    • 如果响应总是小于175字节,则使用专用网卡进行此服务,并减小网络帧大小以增加每秒发送的包 .

    • 不要让服务器做其他事情(比如提供正常的网页)

    • ......

相关问题