Redis
 sql >> Teknologi Basis Data >  >> NoSQL >> Redis

Bagaimana cara meningkatkan penggunaan CPU server Redis?

Saya ragu memaksimalkan penggunaan CPU Redis akan menguntungkan desain backend Anda. Pertanyaan yang tepat adalah apakah Redis cukup efisien untuk mempertahankan throughput Anda pada latensi tertentu. Redis adalah server single-threaded:pada konsumsi CPU 80%, latensi kemungkinan akan sangat buruk.

Saya sarankan Anda mengukur latensi saat redis-benchmark berfungsi untuk melihat apakah itu dapat diterima untuk kebutuhan Anda sebelum mencoba meningkatkan konsumsi CPU Redis. Opsi --latency dari redis-cli dapat digunakan untuk ini:

  • meluncurkan redis-server
  • coba redis-cli --latency, catat nilai rata-rata, hentikan
  • di jendela lain, mulai tolok ukur, dan pastikan berjalan sebentar
  • coba redis-cli --latency, catat nilai rata-rata, hentikan
  • hentikan tolok ukur
  • bandingkan dua nilai rata-rata

Sekarang, jika Anda benar-benar ingin meningkatkan konsumsi CPU Redis, Anda memerlukan program klien yang efisien (seperti redis-benchmark), yang mampu menangani beberapa koneksi secara bersamaan, baik beberapa contoh program klien Anda.

Lua adalah bahasa yang ditafsirkan dengan cepat, tetapi masih merupakan bahasa yang ditafsirkan. Ini akan menjadi satu atau dua kali lipat lebih lambat dari kode C. Redis jauh lebih cepat dalam mem-parsing/menghasilkan protokolnya daripada lua-redis, jadi Anda tidak akan dapat memenuhi Redis dengan klien Lua yang unik (kecuali jika Anda menggunakan perintah O(n) Redis - lihat nanti).

webdis diimplementasikan dalam C, dengan pustaka klien yang efisien, tetapi harus menguraikan protokol http/json yang kebetulan lebih bertele-tele dan kompleks daripada protokol Redis. Kemungkinan mengkonsumsi lebih banyak CPU daripada Redis itu sendiri untuk sebagian besar operasi. Jadi sekali lagi, Anda tidak akan memenuhi Redis dengan satu instance webdis.

Berikut adalah beberapa contoh untuk menjenuhkan Redis dengan beberapa klien Lua.

Jika belum, saya sarankan Anda melihat halaman benchmark Redis terlebih dahulu.

Jika Anda menjalankan tolok ukur pada kotak yang sama dengan Redis:

Poin kuncinya adalah mendedikasikan inti untuk Redis, dan menjalankan program klien pada inti lainnya. Di Linux, Anda dapat menggunakan perintah taskset untuk ini.

# 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

Program Lua harus menggunakan pipelining untuk memaksimalkan throughput dan mengurangi aktivitas sistem.

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

Di sistem saya, program Lua membutuhkan lebih dari 4 kali CPU Redis, jadi Anda memerlukan lebih dari 4 core untuk menjenuhkan Redis dengan metode ini (kotak 6 core seharusnya baik-baik saja).

Jika Anda menjalankan tolok ukur pada kotak yang berbeda dari Redis:

Kecuali jika Anda menjalankan mesin virtual yang kekurangan CPU, hambatan kemungkinan adalah jaringan dalam kasus itu. Saya rasa Anda tidak dapat memenuhi Redis dengan tautan kurang dari 1 GbE.

Pastikan untuk menyalurkan kueri Anda sejauh mungkin (lihat program Lua sebelumnya) untuk menghindari kemacetan latensi jaringan, dan mengurangi biaya interupsi jaringan pada CPU (mengisi paket ethernet). Coba jalankan Redis pada inti yang tidak terikat ke kartu jaringan (dan proses interupsi jaringan). Anda dapat menggunakan alat seperti htop untuk memeriksa poin terakhir ini.

Cobalah untuk menjalankan klien Lua Anda di berbagai mesin lain dari jaringan jika Anda bisa. Sekali lagi Anda akan membutuhkan banyak klien Lua untuk memenuhi Redis (6-10 seharusnya baik-baik saja).

Dalam beberapa kasus, proses Lua yang unik sudah cukup:

Sekarang, dimungkinkan untuk menjenuhkan Redis dengan satu klien Lua jika setiap kueri cukup mahal. Ini contohnya:

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

Program ini mengisi daftar dengan 1 juta item, dan kemudian menggunakan perintah lrange untuk mengambil 10 item dari tengah daftar (kasus terburuk untuk Redis). Jadi setiap kali kueri dijalankan, 500 ribu item dipindai oleh server. Karena hanya 10 item yang dikembalikan, mereka cepat diurai oleh lua-redis yang tidak akan menggunakan CPU. Dalam situasi ini, semua konsumsi CPU akan berada di sisi server.

Kata-kata terakhir

Mungkin ada klien Redis yang lebih cepat daripada redis-lua:

  • https://github.com/agladysh/lua-hiredis (berdasarkan yang disewa)
  • https://github.com/agladysh/ljffi-hiredis (berdasarkan yang disewa, menggunakan luajit FFI)

Anda mungkin ingin mencobanya.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Transaksi yang Diketik Redis

  2. Apakah ini kasus penggunaan yang baik untuk Redis pada ServiceStack REST API?

  3. Apakah Redis hanya cache?

  4. Koneksi Redis melalui soket di Node.js

  5. Menyiapkan Redis di Webfaction