Tôi nghi ngờ việc tối đa hóa việc sử dụng CPU của Redis sẽ có lợi cho thiết kế phụ trợ của bạn. Câu hỏi đúng là liệu Redis có đủ hiệu quả để duy trì thông lượng của bạn ở một độ trễ nhất định hay không. Redis là một máy chủ đơn luồng:ở mức tiêu thụ CPU 80%, độ trễ có thể sẽ rất tồi tệ.
Tôi khuyên bạn nên đo độ trễ trong khi redis-benchmark đang hoạt động để xem liệu nó có được chấp nhận cho nhu cầu của bạn hay không trước khi cố gắng tăng mức tiêu thụ CPU của Redis. Tùy chọn --latency của redis-cli có thể được sử dụng cho việc này:
- khởi chạy redis-server
- thử redis-cli --latency, lưu ý giá trị trung bình, dừng lại
- trong một cửa sổ khác, bắt đầu điểm chuẩn và đảm bảo rằng nó sẽ chạy một lúc
- thử redis-cli --latency, lưu ý giá trị trung bình, dừng lại
- dừng điểm chuẩn
- so sánh hai giá trị trung bình
Bây giờ, nếu bạn thực sự muốn tăng mức tiêu thụ CPU của Redis, bạn cần một chương trình khách hiệu quả (như redis-benchmark), có thể xử lý nhiều kết nối đồng thời, hoặc nhiều phiên bản của chương trình khách của bạn.
Lua là một ngôn ngữ được thông dịch nhanh, nhưng nó vẫn là một ngôn ngữ thông dịch. Nó sẽ chậm hơn một hoặc hai lệnh cường độ so với mã C. Redis phân tích cú pháp / tạo giao thức của nó nhanh hơn nhiều so với lua-redis, vì vậy bạn sẽ không thể bão hòa Redis bằng một ứng dụng khách Lua duy nhất (ngoại trừ nếu bạn sử dụng các lệnh O (n) Redis - xem sau).
webdis được triển khai bằng C, với một thư viện máy khách hiệu quả, nhưng phải phân tích cú pháp các giao thức http / json thường dài dòng và phức tạp hơn giao thức Redis. Nó có thể tiêu tốn nhiều CPU hơn chính Redis cho hầu hết các hoạt động. Vì vậy, một lần nữa, bạn sẽ không bão hòa Redis bằng một phiên bản webdis duy nhất.
Dưới đây là một số ví dụ để bão hòa Redis với nhiều ứng dụng khách Lua.
Nếu nó chưa được thực hiện, tôi khuyên bạn nên xem trang điểm chuẩn của Redis trước.
Nếu bạn chạy điểm chuẩn của mình trên cùng một hộp với Redis:
Điểm mấu chốt là dành một lõi cho Redis và chạy các chương trình khách trên các lõi khác. Trên Linux, bạn có thể sử dụng lệnh tasket cho việc này.
# 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
Chương trình Lua nên sử dụng pipelining để tối đa hóa thông lượng và giảm hoạt động của hệ thống.
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
Trên hệ thống của tôi, chương trình Lua chiếm nhiều hơn 4 lần CPU của Redis, vì vậy bạn cần nhiều hơn 4 lõi để bão hòa Redis bằng phương pháp này (hộp 6 lõi sẽ ổn).
Nếu bạn chạy điểm chuẩn của mình trên một hộp khác với Redis:
Ngoại trừ trường hợp bạn chạy trên các máy ảo bị thiếu CPU, nút cổ chai có thể sẽ là mạng trong trường hợp đó. Tôi không nghĩ rằng bạn có thể bão hòa Redis bằng bất kỳ thứ gì ít hơn một liên kết 1 GbE.
Đảm bảo truyền tải các truy vấn của bạn càng xa càng tốt (xem chương trình Lua trước đó) để tránh tắc nghẽn độ trễ mạng và giảm chi phí gián đoạn mạng trên CPU (lấp đầy các gói ethernet). Cố gắng chạy Redis trên lõi không bị ràng buộc với card mạng (và xử lý sự cố gián đoạn mạng). Bạn có thể sử dụng các công cụ như htop để kiểm tra điểm cuối cùng này.
Cố gắng chạy ứng dụng Lua của bạn trên nhiều máy khác trong mạng nếu bạn có thể. Một lần nữa, bạn sẽ cần một số lượng lớn khách hàng Lua để bão hòa Redis (6-10 là ổn).
Trong một số trường hợp, quy trình Lua duy nhất là đủ:
Giờ đây, có thể bão hòa Redis bằng một ứng dụng khách Lua nếu mỗi truy vấn đủ đắt. Đây là một ví dụ:
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
Chương trình này điền vào danh sách 1 triệu mục, sau đó sử dụng lệnh lrange để tìm nạp 10 mục từ giữa danh sách (trường hợp xấu nhất đối với Redis). Vì vậy, mỗi khi một truy vấn được thực thi, 500K mục sẽ được máy chủ quét. Bởi vì chỉ có 10 mục được trả lại, chúng sẽ nhanh chóng được lua-redis phân tích cú pháp, điều này sẽ không tiêu tốn CPU. Trong trường hợp này, tất cả mức tiêu thụ CPU sẽ ở phía máy chủ.
Lời cuối cùng
Có thể có các ứng dụng Redis nhanh hơn redis-lua:
- https://github.com/agladysh/lua-hiredis (dựa trên Rentis)
- https://github.com/agladysh/ljffi-hiredis (dựa trên Rentis, sử dụng luajit FFI)
Bạn có thể muốn thử chúng.