当前位置: 首页 > 面试题库 >

如何提高Redis服务器的CPU使用率?

齐鸿光
2023-03-14
问题内容

我的目标是使我们的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服务器。

但是在使用其他客户端工具(例如redis-lua或webdis)时,最大CPU使用率不到60%。

我在webdis和中浏览了一些代码redis-luawebdis取决于hiredis,并且redis- lua在Lua中实现,并且取决于socket(lua-socket)。

与Redis基准相比,这些客户端是否太慢,并且无法最大化Redis CPU的使用量?

我还浏览了中的一些代码redis-benchmark.c。基准测试的主要工作在中完成aeMain。似乎redis- benchmark使用Redis的快速代码,而我的测试client(webdisredis-lua)则没有。

目前,我的客户有两种选择:

  1. 采用 redis-lua
  2. 使用类似的工具 webdis

但是,这两个不能最大化Redis的CPU利用率(小于60%)。还有其他选择吗?

或者,是否有可能在redis-benchmark工具本身之外充分利用redis-server ?


问题答案:

我怀疑最大限度地提高Redis的CPU使用率会有益于您的后端设计。正确的问题是Redis是否足够有效以在给定的延迟下维持吞吐量。Redis是单线程服务器:CPU消耗80%时,延迟可能非常糟糕。

我建议您在尝试增加Redis CPU消耗之前,在redis-benchmark工作时测量延迟,以查看它是否可以满足您的需求。redis-cli的–
latency选项可用于此目的:

  • 启动redis服务器
  • 尝试redis-cli –latency,注意avg值,将其停止
  • 在另一个窗口中,启动基准测试,并确保其运行一段时间
  • 尝试redis-cli –latency,注意avg值,将其停止
  • 停止基准
  • 比较两个平均值

现在,如果您确实想增加Redis CPU的使用量,则需要一个高效的客户端程序(例如redis-
benchmark),该客户端程序能够同时处理多个连接,或者是客户端程序的多个实例。

Lua是一种快速的解释语言,但仍然是一种解释语言。这将比C代码慢一两个数量级。Redis在解析/生成其协议方面比lua-
redis快得多,因此您将无法使用唯一的Lua客户端使Redis饱和(除非您使用O(n)Redis命令-稍后请参见)。

webdis使用高效的客户端库以C语言实现,但必须解析http /
json协议,该协议比Redis协议更为冗长和复杂。对于大多数操作,它可能比Redis本身消耗更多的CPU。再次重申,您不会使用单个webdis实例饱和Redis。

这是一些使Redis带有多个Lua客户端的示例。

如果尚未完成,建议您首先查看Redis基准页面。

如果您在与Redis相同的框中运行基准测试:

关键是将一个内核专用于Redis,并在其他内核上运行客户端程序。在Linux上,可以为此使用tasket命令。

# 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 & done

Lua程序应使用流水线以最大化吞吐量并减少系统活动。

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程序占用的Redis CPU数量是Redis的4倍以上,因此您需要4个以上的内核才能使Redis达到饱和(6核的盒子应该没问题)。

如果您在与Redis不同的机器上运行基准测试:

除非您在CPU不足的虚拟机上运行,​​否则瓶颈可能是网络。我不认为您可以使用小于1 GbE的链路来使Redis饱和。

确保尽可能地对查询进行管线化(请参见前面的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最坏的情况)。因此,每次执行查询时,服务器都会扫描500K项。因为仅返回10个项目,所以它们可以通过lua-
redis进行快速解析,而不会消耗CPU。在这种情况下,所有CPU消耗都将在服务器端。

最后的话

Redis客户端可能比redis-lua更快:

  • https://github.com/agladysh/lua-hiredis(基于hiredis)
  • https://github.com/agladysh/ljffi-hiredis(基于hiredis,使用luajit FFI)

您可能想尝试一下。



 类似资料:
  • 使用的是 2 核的腾讯云轻量服务器,这个 zapppp 进程几乎占用了所有 CPU 资源,有可能是一个挖矿程序,使用常规的方法都无法终结这个进程。前几天收到邮件说服务器的 22 端口存在攻击行为,我怀疑是攻击者通过破解 ssh 登录密码登录到服务器然后植入恶意程序。 请问一下如何完整地修复这个问题?

  • 我有: a)1台服务器(4vcpu,8GB)运行hazelcast节点, b)1台(4vcpu,8MB)运行tomcat 7上的hazelcash性能中心。 两台服务器都在同一个本地网络中。 我已经测试了2个场景:< br >场景1)我已经开始了a)和b)。没有传输数据。a)上的cpu使用率为0-10%。< br >情景2)我已经开始了a)和b)。我已经将大量数据转移到a)上进行处理,并一直等到它

  • 问题内容: 我显然正在运行一个实例,因为当我尝试通过输入来启动新服务器时,遇到了以下问题: 我不知道如何停止此服务器并启动新服务器。 在CLI中键入命令时,可以追加任何命令吗? 我的操作系统是Ubuntu 10.04。 问题答案: 连接到节点实例并使用shutdown命令,或者如果您在ubuntu上,则可以尝试通过init.d重新启动Redis服务器: 或停止/启动它: 在Mac上

  • 我是一名内网视频网站管理员。目前我们的网站在局域网内部署,向用户提供在线视频服务。在访问量大时,整体网站访问速度很慢。 服务器环境是centos7 apache mysql php,使用海洋cms作为内容管理系统。 在访问量大时(80端口连接数大约1200),使用top命令查看发现load average达到上百(cpu仅有8核心),并且大部分cpu使用都是wa状态。 由于服务器使用的是挂载的网络

  • Redis 服务器 Redis 服务器命令主要是用于管理 redis 服务。 实例 以下实例演示了如何获取 redis 服务器的统计信息: Redis 服务器命令 Redis Bgrewriteaof 命令 Redis Bgrewriteaof 命令用于异步执行一个 AOF(AppendOnly File) 文件重写操作。重写会创建一个当前 AOF 文件的体积优化版本。 即使 Bgrewritea

  • 现在,我意识到当前的master没有太多内存,所以我在这个特定的服务器上停止了sentinel和redis实例。并在一台新机器上进行了相同的设置。所以,我仍然有相同的部署,3个redis实例和3个哨兵。 问题是,现在哨兵们说,主人倒下了,因为他们认为主人是我移除的服务器。我应该做些什么来告诉sentinel它不需要在循环中包括服务器。