2013-04-25 51 views
2

我的目標是在Redis服務器上使用大約80%的CPU, 這可以使我們的後端服務器設計充滿活力。如何提高Redis服務器的CPU使用率?

在使用Redis的本身的基準,這是很容易達到約100%的CPU使用率:

$ redis-benchmark -h 192.168.1.6 -n 1000000 -c 50 

在這次測試中我們分配50個客戶端,以推動我們的Redis服務器1,000,000請求(192.168.1.6)

但是,當使用一些其他客戶端工具(如redis-luawebdis)時,CPU使用率最高不到60%。

我瀏覽了的一些代碼webdisreids-luawebdis取決於hiredisredis的-LUA在Lua,實現其中基於插座(LUA插座)。這些肥胖者會影響測試結果嗎?

我也瀏覽在redis的-benchmark.c一些代碼,基準的主要工作在aeMain做,好像是 的redis的基準測試使用的代碼在Redis的,和我的測試客戶端(webdisredis-lua)不。

目前我的客戶有兩種選擇,使用Redis的 - 盧阿或做類似webdis,但是這兩者不作 很好的使用Redis的(小於60%)的,有沒有更多的選擇?或者如何在redis服務器上有很好的使用,除了 redis-benchmark本身?

回答

6

我懷疑最大限度地提高Redis的CPU使用率會有利於您的後端設計。正確的問題是Redis是否足夠有效地在給定的延遲時間內維持吞吐量。 Redis是一款單線程服務器:在80%的CPU消耗下,延遲可能會非常糟糕。

我建議你測量延遲,而在嘗試增加Redis CPU消耗之前,redis-benchmark正在努力查看它是否可以滿足您的需求。 Redis的-CLI的--latency選項可用於此:

  • 推出的Redis服務器
  • 試Redis的-CLI --latency,記下平均價值,阻止它在另一個窗口
  • ,啓動基準,並確保它運行一段
  • 試Redis的-CLI --latency,記下平均數值,停止
  • 停止基準
  • 比較兩個值平均

現在,如果您真的想增加Redis CPU消耗,您需要一個高效的客戶端程序(如redis-benchmark),能夠同時處理多個連接,無論是多個客戶端程序實例。

Lua是一種快速解釋的語言,但它仍然是一種解釋型語言。它將比C代碼慢一個或兩個數量級。 Redis在解析/生成協議方面比lua-redis快得多,所以你將無法用獨特的Lua客戶端來飽和Redis(除非你使用O(n)Redis命令 - 請參閱後面的內容)。

webdis以C語言實現,具有高效的客戶端庫,但必須解析恰好比Redis協議更冗長和複雜的http/json協議。對於大多數操作,它可能比Redis本身消耗更多的CPU。所以再次,你不會用一個webdis實例來飽和Redis。

以下是一些使Redis與多個Lua客戶端飽和的示例。

如果還沒有完成,我建議你先看看the Redis benchmark page

如果在同一個盒子作爲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 & 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的4倍以上的CPU,所以你需要4個以上的核心飽和的Redis用這種方法(6芯盒應該是罰款)。

如果運行在不同的盒子比Redis的基準測試:

除非你對CPU餓死虛擬機上運行,​​瓶頸可能會在這種情況下,網絡。我不認爲你可以用任何少於1GbE的鏈接來飽和Redis。

爲了避免網絡延遲瓶頸和減少CPU上的網絡中斷成本(填充以太網數據包),請確保儘可能管道化您的查詢(請參閱前面的Lua程序)。嘗試在未綁定到網卡的核心上運行Redis(並處理網絡中斷)。您可以使用htop等工具來檢查最後一點。

嘗試在網絡的各種其他機器上運行您的Lua客戶端(如果可以的話)。同樣,你需要大量的Lua客戶端來使Redis飽和(6-10應該沒問題)。

在某些情況下,唯一的Lua的過程就足夠了:

現在,有可能飽和的Redis使用單個Lua的客戶,如果每個查詢是夠貴的。下面是一個例子:

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命令,從列表的中間(對於Redis的最壞情況)取10個項目。所以每次執行查詢時,服務器都會掃描500K項目。因爲只有10個項目被返回,所以它們很快被lua-redis解析,這將不會消耗CPU。在這種情況下,所有的CPU消耗將在服務器端。

最後的話

有可能更快,Redis的客戶比Redis的 - 盧阿:

你可能想嘗試它們。