Redis 效能測試記錄
雖然 Redis 本身也提供redis-benchmark
工具來對 Redis 的效能進行測試,但為了對測試維度自由定製,我們還是通過自己編寫指令碼的方式來測試。
Redis 的官方文件也提到了,簡單的起一個迴圈,然後在迴圈中向 Redis 傳送操作命令,其實不是對 Redis 進行效能測試,而是對網路延遲進行測試。為了真正測試 Redis 的併發效能,需要使用多個 Redis 連線,或者使用 pipelining 來聚合多個命令。當然也可以使用多執行緒或者多程序。
我們使用 Python 指令碼來作為 Redis 的測試工具,並採用每個程序一個 Redis 連線的方案。
測試指令碼如下所示:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import time
import datetime
from multiprocessing import Process
import redis
def write_worker(n):
print 'in write worker: %d, time: %s' % (n, datetime.datetime.now())
r = redis.StrictRedis(host='10.88.115.114', port=6380)
s = 'a' * 1024 * 1024 * 10
t1 = time.time()
bigkey = 'bigkey%d' % (n + 100)
r.set(bigkey, s)
t2 = time.time()
print 'write time: %f' % (t2 - t1)
def read_worker(n):
print 'in read worker: %d, time: %s' % (n, datetime.datetime.now())
r = redis.StrictRedis(host='10.88.115.114', port=6380)
t1 = time.time()
bigkey = 'bigkey%d' % n
r.get(bigkey)
t2 = time.time()
print 'read time: %f' % (t2 - t1)
def test():
read_processes = []
for i in range(0, 100):
read = Process(target=read_worker, args=(i,))
read.start()
read_processes.append(read)
write_processes = []
for i in range(0, 100):
write = Process(target=write_worker, args=(i,))
write.start()
write_processes.append(write)
for write in write_processes:
write.join()
for read in read_processes:
read.join()
print 'end press test'
if __name__ == '__main__':
test()
redis-py 的StrictRedis
已提供了連線池的功能的,可以在多執行緒中直接使用,這裡我們使用了多程序的方式,並採用每個程序都使用獨立的一個StrictRedis
例項。
在上面的程式碼中,我們起了大量的讀寫程序。對 Redis 的寫入操作中每次傳送一個SET
的請求,寫入的資料大小為 100 MB,讀操作則每次讀取GET
100 MB的資料(需要提前準備GET
請求的 key 的資料)。測試程式的目的是為了測試 Redis 在處理較高併發時,大資料讀寫的效能。
測試結果在這裡就不貼不出來,有興趣的讀者也可以執行一下這個 Python 指令碼,就可以得到測試結果了。從測試結果來看,Redis 的效能還是很優秀的。
這裡重點提一下測試過程中 Redis 服務會報錯的問題。
在寫入大量的資料(100個10MB,即1GB)後,Redis 程序開始出現以下日誌:
[2418] 21 Apr 09:38:24.041 * 10 changes in 300 seconds. Saving…
[2418] 21 Apr 09:38:24.042 # Can’t save in background: fork: Cannot allocate memory
客戶端執行寫入命令會報錯:
127.0.0.1:6380> set key value
(error) MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.
從網上查詢 Redis 的資料可以知道,這是由於 Redis 開啟了 RDB 功能所致。RDB 用於儲存 Redis 的資料快照,將資料快照資料持久化到硬碟中。以下是 Redis 的 RDB 預設配置:
save 900 1
save 300 10
save 60 10000
其含義是900秒內有1次修改,300秒內有10次修改,60秒內有10000秒修改,都會將照資料持久化到磁碟中。
要解決 Redis 報錯的問題,可以把 RDB 功能關閉,或者通過優化 Linux 記憶體配置優化解決。具體可以參考《LINUX下REDIS記憶體優化》。
sysctl vm.overcommit_memory=1
以 root 許可權執行此命令後,再對 Redis 服務進行重啟,然後執行測試程式,不再出現 Redis 報錯的問題。
需要指出的是,按照網上很多文章說的,可以通過修改 redis.conf 配置中的stop-writes-on-bgsave-error
選項的方式來解決報錯的問題,實際上只是把問題掩蓋起來而。因為採用下面的配置:
stop-writes-on-bgsave-error no
RDB 功能雖然不能儲存 Redis 資料快照了,但 Redis 仍可繼續接受新的 Redis 請求。
為了從根本解決 RDB 報錯的問題,還是應該通過修改vm.overcommit_memory
Linux 核心引數的方式來解決。