Redis性能调优

20
我们正在运行一个Web应用程序,已经从memcached切换到redis(2.4)进行缓存。现在我们对redis的性能有些失望。 Redis在同一台服务器上运行,我们只使用非常简单的GET和SET操作。在某些请求中,我们会对缓存值进行大量使用,这会导致我们向Redis发送多达300个GET请求,但这些请求需要高达150ms的时间。我们有大约200,000个活动键,并且每秒大约有1,000个redis请求。磁盘I / O,RAM或CPU没有问题。由于现有代码的存在,我们无法将redis请求简单地分组。 memcached的速度大约快了4倍。
我们喜欢redis的是,我们不需要任何缓存预热,并且将来可以使用更高级的数据存储功能。我们期望redis的表现类似于memcached。因此,也许我们在配置中错过了一些内容,基本上是默认配置。 您是否知道有关redis性能调优的最佳实践?

Redis运行在同一台服务器上,是和客户端一起运行的,还是和运行memcached的那个服务器一起运行的?如果一个Redis请求需要150毫秒的时间,那么你可能是在访问交换空间/磁盘,而不是内存。或者你是指300个请求总共需要150毫秒的时间? - Joachim Isaksson
这是一个每秒大约有100个Apache请求的Web应用程序。Redis运行在与Web应用程序本身和MySQL数据库服务器相同的主机上,但我们计划很快将Apache迁移到3个负载均衡服务器上。当前服务器有大约64GB的RAM,Redis占用大约100MB。有足够的空闲内存,CPU或IO没有问题。服务器不会交换到磁盘。是的,我指的是300个请求需要150毫秒,但在相同条件下,Memcached只需要40毫秒。 - ak2
1
我能想到的唯一问题是,如果你在所有请求中使用共享连接到Redis而不是每个Web请求一个连接,那么你可能会遇到Redis的延迟问题,但是在每秒1000个请求下,你不应该看到太差的延迟。抱歉,今天我没有什么真正有用的建议 :) - Joachim Isaksson
3个回答

30

首先,您可能希望阅读Redis基准测试页面。它提供了一个很好的摘要,介绍了调整Redis的主要要点。

即使您不使用流水线处理,300个GET在150毫秒内并不十分高效。这意味着平均延迟为500微秒。但实际上,这取决于您对象的大小。对象越大,延迟就越高。在我的非常老旧的2GHz AMD盒子上,我可以测量小对象(几个字节)的150微秒延迟。

要快速检查Redis实例的平均延迟,您可以使用:

$ redis-cli --latency

请确保使用较新的Redis版本(不是2.4),以获得此选项。 注意:2.4现在相当陈旧,请使用Redis 2.6 - 如果需要,编译自己的Redis版本非常简单。

要快速运行基准测试以研究延迟,请启动:

$ redis-benchmark -q -n 10000 -c 1 -d average_size_of_your_objects_in_bytes

它使用独特的连接方式而没有使用流水线技术,因此延迟可以从吞吐量中推导出来。尝试将这些基准测试结果与应用程序测量得到的数字进行比较。

您可能需要检查以下几点:

  • 您使用哪个Redis客户端库?使用哪种开发语言?对于某些脚本语言,您需要安装hiredis模块以获得高效的客户端。
  • 您的机器是虚拟机吗?使用哪个操作系统?
  • Redis的连接是否持久?(即您不应在应用程序服务器的每个HTTP请求中连接/断开连接)。

为什么使用memcached更好?嗯,单个memcached实例肯定更具可扩展性,并且可能比单个Redis实例响应更快,因为它可以在多个线程上运行。Redis很快,但是单线程-所有命令的执行都是串行的。因此,当连接执行某个命令时,所有其他客户端都必须等待-给定命令的差延迟也会影响所有待处理命令。一般来说,在低吞吐量下,性能是相当可比的。

在每秒1000次查询(按Redis或memcached标准为低吞吐量)时,我认为您的问题更可能是客户端方面的问题(即客户端库的选择、连接/断开连接等),而不是Redis服务器本身的问题。

最后,我应该提到,如果您在每个HTTP请求中生成大量的Redis查询,请尽可能使用流水线技术管道化您发送到Redis的命令。这确实是开发高效Redis应用程序的关键点。

如果您的应用程序服务器与Redis在同一台机器上,则还可以使用Unix域套接字而不是TCP回环连接到Redis。它会略微提高性能(在不使用流水线技术时增加50%的吞吐量)。


“所有命令的执行都是串行化的”:您能否对这个说法提供更多细节?在我看来,这似乎意味着当一个命令正在运行时,即使在其他连接上也不能运行任何其他命令。这是 Redis 实现命令原子性的方式吗? - akonsu
没错。请参见https://dev59.com/Zmkv5IYBdhLWcg3wlR31#10495458。 - Didier Spezia

1

检查Redis是否使用操作系统交换内存。如果是,则会增加延迟。 要查找,请在此处搜索“通过交换引起的延迟”:http://redis.io/topics/latency

如果您的服务器硬件支持NUMA,请使用numactl启动redis-server。 如果您使用NUMA启动redis-server,请不要忘记关闭sysctl中的区域回收模式(vm.zone_reclaim_mode=0)。


0
尝试在Lua脚本中编写300个GET请求的脚本。虽然您的客户端代码在本地运行,但由于节省了对TCP/IP堆栈的触摸时间,因此应该可以更快地工作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接