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

mengapa sangat lambat dengan 100.000 catatan saat menggunakan pipa di redis?

Ada beberapa poin yang perlu Anda pertimbangkan sebelum menulis benchmark tersebut (dan terutama benchmark menggunakan JVM):

  • pada sebagian besar mesin (fisik), Redis mampu memproses lebih dari 100K ops/dtk saat pipelining digunakan. Patokan Anda hanya berurusan dengan 100 ribu item, sehingga tidak bertahan cukup lama untuk menghasilkan hasil yang berarti. Selain itu, tidak ada waktu untuk memulai tahapan JIT secara berurutan.

  • waktu absolut bukanlah metrik yang sangat relevan. Menampilkan throughput (yaitu jumlah operasi per detik) sambil menjaga benchmark tetap berjalan setidaknya selama 10 detik akan menjadi metrik yang lebih baik dan lebih stabil.

  • lingkaran dalam Anda menghasilkan banyak sampah. Jika Anda berencana untuk membandingkan Jedis+Redis, maka Anda harus menjaga agar program Anda sendiri tetap rendah.

  • karena Anda telah mendefinisikan semuanya ke dalam fungsi utama, loop Anda tidak akan dikompilasi oleh JIT (tergantung pada JVM yang Anda gunakan). Hanya panggilan metode dalam yang mungkin. Jika Anda ingin JIT menjadi efisien, pastikan untuk mengenkapsulasi kode Anda ke dalam metode yang dapat dikompilasi oleh JIT.

  • opsional, Anda mungkin ingin menambahkan fase pemanasan sebelum melakukan pengukuran aktual untuk menghindari penghitungan overhead menjalankan iterasi pertama dengan penerjemah bare-bone, dan biaya JIT itu sendiri.

Sekarang, mengenai pipa Redis, pipa Anda terlalu panjang. 100K perintah dalam pipa berarti Jedis harus membangun buffer 6MB sebelum mengirim apa pun ke Redis. Ini berarti buffer soket (di sisi klien, dan mungkin sisi server) akan jenuh, dan Redis juga harus berurusan dengan buffer komunikasi 6 MB.

Selain itu, tolok ukur Anda masih sinkron (menggunakan pipa tidak secara ajaib membuatnya tidak sinkron). Dengan kata lain, Jedis tidak akan mulai membaca balasan hingga kueri terakhir dari saluran pipa Anda telah dikirim ke Redis. Ketika saluran pipa terlalu panjang, itu berpotensi memblokir banyak hal.

Pertimbangkan untuk membatasi ukuran pipa hingga 100-1000 operasi. Tentu saja, ini akan menghasilkan lebih banyak perjalanan pulang pergi, tetapi tekanan pada tumpukan komunikasi akan dikurangi ke tingkat yang dapat diterima. Misalnya, perhatikan program berikut:

import redis.clients.jedis.*;
import java.util.*;

public class TestPipeline {

    /**
     * @param args
     */

    int i = 0; 
    Map<String, String> map = new HashMap<String, String>();
    ShardedJedis jedis;  

    // Number of iterations
    // Use 1000 to test with the pipeline, 100 otherwise
    static final int N = 1000;

    public TestPipeline() {
      JedisShardInfo si = new JedisShardInfo("127.0.0.1", 6379);
      List<JedisShardInfo> list = new ArrayList<JedisShardInfo>();
      list.add(si);
      jedis = new ShardedJedis(list);
    } 

    public void push( int n ) {
     ShardedJedisPipeline pipeline = jedis.pipelined();
     for ( int k = 0; k < n; k++) {
      map.put("id", "" + i);
      map.put("name", "lyj" + i);
      pipeline.hmset("m" + i, map);
      ++i;
     }
     pipeline.sync(); 
    }

    public void push2( int n ) {
     for ( int k = 0; k < n; k++) {
      map.put("id", "" + i);
      map.put("name", "lyj" + i);
      jedis.hmset("m" + i, map);
      ++i;
     }
    }

    public static void main(String[] args) {
      TestPipeline obj = new TestPipeline();
      long startTime = System.currentTimeMillis();
      for ( int j=0; j<N; j++ ) {
       // Use push2 instead to test without pipeline
       obj.push(1000); 
       // Uncomment to see the acceleration
       //System.out.println(obj.i);
     }
     long endTime = System.currentTimeMillis();
     double d = 1000.0 * obj.i;
     d /= (double)(endTime - startTime);
     System.out.println("Throughput: "+d);
   }
 }

Dengan program ini, Anda dapat menguji dengan atau tanpa pipelining. Pastikan untuk meningkatkan jumlah iterasi (parameter N) saat pipelining digunakan, sehingga berjalan setidaknya selama 10 detik. Jika Anda menghapus komentar println di loop, Anda akan menyadari bahwa program ini lambat di awal dan akan menjadi lebih cepat saat JIT mulai mengoptimalkan sesuatu (itulah sebabnya program harus berjalan setidaknya beberapa detik untuk memberikan hasil yang berarti).

Pada perangkat keras saya (kotak Athlon lama), saya bisa mendapatkan throughput 8-9 kali lebih banyak saat pipa digunakan. Program ini dapat ditingkatkan lebih lanjut dengan mengoptimalkan pemformatan kunci/nilai di loop dalam dan menambahkan fase pemanasan.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Bagaimana saya bisa mendapatkan nilai dari Redis dan memasukkannya ke dalam variabel di NGiNX?

  2. Cara membuat kacang FindByIndexNameSessionRepository

  3. ConnectionMultiplexer.Hubungkan terputus saat menghubungkan ke server redis

  4. Pencari kecocokan multi-parameter dengan Redis

  5. Predis dengan laravel 5.5 Tidak ada koneksi yang tersedia di kumpulan di Aggregate/RedisCluster.php:337