我的目标是使我们的Redis服务器在生产中达到大约80%的CPU利用率。这将有利于我们的后端服务器设计,确保我们没有充分利用CPU,同时也为增长和增长留出了一些空间。
当使用Redis自己的基准测试工具redis-benchmark时,很容易达到100%的CPU使用率:
$ redis-benchmark -h 192.168.1.6 -n 1000000 -c 50在这个基准上,我们分配了50个客户端将1,000,000个请求推送到Redis服务器。
但是,在使用其他一些客户端工具(如雷迪斯-卢阿或webdis)时,最大CPU使用率不到60%。
我在webdis和redis-lua中浏览了一些代码。webdis依赖于hiredis,redis-lua在Lua中实现,并且依赖于套接字(lua-socket)。
与Redis基准测试相比,这些客户端是否太慢,并且无法最大化Redis CPU消耗?
我还浏览了redis-benchmark.c中的一些代码。基准测试的主要工作是用aeMain完成的。redis-benchmark似乎使用来自Redis的快速代码,而我的测试客户端(webdis和redis-lua)则不使用。
目前,我的客户有两个选择:
redis-luawebdis这样的工具但是,这两种方法并不能最大限度地提高Redis的CPU利用率(不足60%)。还有别的选择吗?
或者,是否有可能充分利用redis-benchmark工具本身之外的redis服务器?
发布于 2013-04-25 12:19:37
我怀疑最大化CPU使用Redis将有益于您的后端设计。正确的问题是Redis是否足够有效地在给定的延迟时间内维持吞吐量。Redis是一个单线程服务器:在80%的CPU消耗下,延迟可能会非常糟糕。
我建议您在Redis工作时测量延迟,在尝试增加Redis CPU消耗之前,看看它是否可以满足您的需要。redis-cli的--延迟选项可用于此:
现在,如果您真的想增加Redis CPU的消耗,那么您需要一个高效的客户端程序(比如redis-benchmark),它可以同时处理多个连接,或者是客户机程序的多个实例。
Lua是一种快速解释的语言,但它仍然是一种解释语言。它将比C代码慢一两个数量级。Redis在解析/生成其协议方面比later快得多,因此您将无法使用惟一的Lua客户端(除非使用O(n) Redis命令-请参阅稍后)。
webdis是用C实现的,它有一个高效的客户端库,但是必须解析http/json协议,这些协议比Redis协议更冗长、更复杂。在大多数操作中,它可能比Redis本身消耗更多的CPU。因此,您不会使用单个webdis实例填充Redis。
下面是一些例子,让Redis能够满足多个Lua客户端的需求。
如果还没有完成,我建议您先看看Redis基准页面。
如果您在与Redis相同的框上运行基准测试::
关键是将一个核心专用于Redis,并在其他核心上运行客户端程序。在Linux上,您可以为此使用taskset命令。
# Start Redis on core 0
taskset -c 0 redis-server redis.conf
# Start Lua programs on the other cores
for x in `seq 1 10` ; do taskset -c 1,2,3 luajit example.lua & doneLua程序应该使用流水线来最大化吞吐量和减少系统活动。
local redis = require 'redis'
local client = redis.connect('127.0.0.1', 6379)
for i=1,1000000 do
local replies = client:pipeline(function(p)
for j=1,1000 do
local key = 'counter:'..tostring(j)
p:incrby(key,1)
end
end)
end在我的系统中,Lua程序占用的CPU是Redis的4倍以上,所以您需要超过4个核心才能使用这种方法来饱和红宝石(一个6核盒应该很好)。
如果您在与Redis不同的框上运行基准测试::
除了在缺乏CPU的虚拟机上运行之外,在这种情况下,瓶颈可能是网络。我不认为你可以用少于1 GbE链接的任何东西来填满红宝石。
一定要尽可能地对查询进行管道处理(请参阅前面的Lua程序),以避免网络延迟瓶颈,并降低CPU上的网络中断(填充以太网数据包)的成本。尝试在不绑定到网卡的核心上运行Redis (并处理网络中断)。您可以使用像htop这样的工具来检查最后一点。
如果可能的话,尝试在网络的其他机器上运行Lua客户端。再一次,你将需要大量的Lua客户来饱和Redis (6-10应该可以)。
在某些情况下,一个惟一的Lua过程就足够了:
现在,如果每个查询都足够昂贵,就可以使用单个Lua客户机填充Redis。下面是一个示例:
local redis = require 'redis'
local client = redis.connect('127.0.0.1', 6379)
for i=1,1000 do
local replies = client:pipeline(function(p)
for j=1,1000 do
p:rpush("toto",i*1000+j)
end
end)
end
N = 500000
for i=1,100000 do
local replies = client:pipeline(function(p)
for j=1,10 do
p:lrange("toto",N, N+10)
end
end)
end该程序用1M项填充列表,然后使用lrange命令从列表中间获取10个项(Redis的最坏情况)。因此,每次执行查询时,服务器都会扫描500 K项。因为只有10个项被返回,所以它们被lua快速解析,而lua不会消耗CPU。在这种情况下,所有的CPU消耗将在服务器端。
最后一词
可能有比Redis -lua更快的redis客户:
你也许想试试。
https://stackoverflow.com/questions/16209605
复制相似问题