Anda dapat menggunakan mekanisme pipelining Redis untuk melakukan operasi batch atau meningkatkan kinerja eksekusi perintah. Pipelining memungkinkan pengiriman beberapa perintah sekaligus ke server, mengurangi latensi jaringan dan meningkatkan efisiensi. Tair (Redis OSS-compatible) mendukung teknik pipelining dari Redis sumber terbuka.
Ikhtisar pipelining
Secara umum, komunikasi antara klien dan server Redis menggunakan mode ping-pong. Dalam mode ini, klien tidak mengirim perintah baru hingga menerima respons atas perintah sebelumnya dari server.
Selain itu, Redis menyediakan mode pipelining di mana klien dapat mengirim perintah dalam batch tanpa menunggu respons. Setelah klien menerima respons, hasil tersebut dicocokkan dengan urutan perintah dan dikembalikan ke frontend.
Gambar berikut mengilustrasikan cara kerja mode ping-pong dan mode pipelining.
Pipelining meningkatkan efisiensi sistem dengan mengurangi latensi jaringan akibat waktu perjalanan bolak-balik (RTT) serta jumlah pemanggilan sistem read() dan write().
Pipelining sangat berguna dalam skenario di mana beberapa perintah perlu segera dikirim ke server tanpa memerlukan respons instan. Dengan demikian, pipelining dapat digunakan sebagai alat pemrosesan batch untuk mengoptimalkan kinerja sistem.
Dalam mode pipelining, pipeline secara eksklusif menggunakan koneksi antara klien dan server, sehingga operasi non-pipeline tidak dapat dilakukan sampai pipeline ditutup. Untuk menjalankan operasi lain secara bersamaan, Anda dapat membuat koneksi khusus untuk pipeline agar terpisah dari operasi lain.
Untuk informasi lebih lanjut, lihat Pipelining Redis.
Peringatan
Pipelining tidak menjamin atomicitas.
Dalam mode pipelining, klien mengirim perintah dalam batch, sedangkan server menyelesaikan setiap perintah secara individual sesuai urutan. Akibatnya, server juga dapat menjalankan perintah dari klien lain. Untuk memastikan atomicitas, Anda dapat menggunakan skrip transaksi atau skrip Lua.
Pipelining tidak mendukung rollback jika terjadi kesalahan.
Jika perintah yang akan dijalankan saling bergantung, hindari penggunaan pipelining.
CatatanBeberapa klien, seperti redis-py, menggunakan perintah transaksi seperti MULTI dan EXEC untuk mensimulasikan pipeline. Penting untuk membedakan antara pipeline dan transaksi serta menggunakannya sesuai kebutuhan spesifik Anda. Jika tidak, kesalahan mungkin terjadi. Untuk informasi lebih lanjut tentang batasan transaksi, lihat Transaksi.
Jika sejumlah besar perintah dijalankan, pipelining mungkin tidak berkinerja optimal karena batasan buffer server dan klien tertentu.
Pipelining pada dasarnya merupakan pola interaksi klien-server yang independen dari arsitektur server. Instans kluster dalam mode proxy, instans kluster dalam mode koneksi langsung, dan instans pembagian baca/tulis semuanya mendukung pipelining.
CatatanArsitektur kluster memiliki batasan inheren. Misalnya, arsitektur kluster tidak mendukung akses lintas slot kunci dalam satu perintah. Jika klien mencoba mengakses kunci yang tidak termasuk dalam node saat ini ke mana klien terhubung, kesalahan
-MOVEDakan terjadi. Saat menggunakan pipelining dalam arsitektur kluster, pastikan bahwa perintah dalam pipeline memenuhi persyaratan arsitektur kluster. Untuk informasi lebih lanjut, lihat Batasan perintah yang didukung oleh instans kluster dan instans pembagian baca/tulis.
Contoh kode
Perbandingan kinerja
Kode berikut menunjukkan perbandingan kinerja antara operasi dengan dan tanpa pipeline:
package pipeline.kvstore.aliyun.com;
import java.util.Date;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;
public class RedisPipelinePerformanceTest {
static final String host = "xxxxxx.m.cnhza.kvstore.aliyuncs.com";
static final int port = 6379;
static final String password = "password";
public static void main(String[] args) {
Jedis jedis = new Jedis(host, port);
// Tentukan kata sandi yang digunakan untuk terhubung ke instans.
String authString = jedis.auth(password);// password
if (!authString.equals("OK")) {
System.err.println("AUTH Gagal: " + authString);
jedis.close();
return;
}
//Jalankan beberapa perintah secara berturut-turut.
final int COUNT=5000;
String key = "KVStore-Tanghan";
//1 ---Tanpa pipeline---
jedis.del(key);//Inisialisasi kunci.
Date ts1 = new Date();
for (int i = 0; i < COUNT; i++) {
//Kirim permintaan dan terima respons.
jedis.incr(key);
}
Date ts2 = new Date();
System.out.println("Tanpa pipeline > nilai adalah: "+jedis.get(key)+" > Waktu berlalu: " + (ts2.getTime() - ts1.getTime())+ "ms");
//2 ----Dengan pipeline---
jedis.del(key);//Inisialisasi kunci.
Pipeline p1 = jedis.pipelined();
Date ts3 = new Date();
for (int i = 0; i < COUNT; i++) {
//Kirim permintaan.
p1.incr(key);
}
//Terima respons.
p1.sync();
Date ts4 = new Date();
System.out.println("Dengan pipeline > nilai adalah:"+jedis.get(key)+" > Waktu berlalu:" + (ts4.getTime() - ts3.getTime())+ "ms");
jedis.close();
}
}Setelah Anda memasukkan endpoint dan kata sandi yang benar untuk terhubung ke instans Tair (Redis OSS-compatible) dan menjalankan kode Java di atas, keluaran berikut akan ditampilkan. Keluaran menunjukkan peningkatan kinerja dengan pipeline.
Tanpa pipeline > nilai: 5.000 > Waktu berlalu: 5.844 ms
Dengan pipeline > nilai: 5000 > Waktu berlalu: 78 msMetode penanganan respons
Saat menggunakan pipelining di Jedis, Anda dapat menggunakan dua metode untuk menangani respons. Untuk informasi lebih lanjut, lihat kode contoh berikut:
package pipeline.kvstore.aliyun.com;
import java.util.List;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.Response;
public class PipelineClientTest {
static final String host = "xxxxxxxx.m.cnhza.kvstore.aliyuncs.com";
static final int port = 6379;
static final String password = "password";
public static void main(String[] args) {
Jedis jedis = new Jedis(host, port);
// Tentukan kata sandi yang digunakan untuk terhubung ke instans.
String authString = jedis.auth(password);// password
if (!authString.equals("OK")) {
System.err.println("AUTH Gagal: " + authString);
jedis.close();
return;
}
String key = "KVStore-Test1";
jedis.del(key);// Inisialisasi kunci.
//-------- Metode 1
Pipeline p1 = jedis.pipelined();
System.out.println("-----Metode 1-----");
for (int i = 0; i < 5; i++) {
p1.incr(key);
System.out.println("Pipeline mengirim permintaan");
}
// Setelah pipeline mengirim semua permintaan, klien mulai menerima respons.
System.out.println("Permintaan terkirim. Mulai menerima respons");
List<Object> responses = p1.syncAndReturnAll();
if (responses == null || responses.isEmpty()) {
jedis.close();
throw new RuntimeException("Pipeline error: tidak ada respons yang diterima");
}
for (Object resp : responses) {
System.out.println("Pipeline menerima respons: " + resp.toString());
}
System.out.println();
//-------- Metode 2
System.out.println("-----Metode 2-----");
jedis.del(key);// Inisialisasi kunci.
Pipeline p2 = jedis.pipelined();
// Deklarasikan respons terlebih dahulu.
Response<Long> r1 = p2.incr(key);
System.out.println("Pipeline mengirim permintaan");
Response<Long> r2 = p2.incr(key);
System.out.println("Pipeline mengirim permintaan");
Response<Long> r3 = p2.incr(key);
System.out.println("Pipeline mengirim permintaan");
Response<Long> r4 = p2.incr(key);
System.out.println("Pipeline mengirim permintaan");
Response<Long> r5 = p2.incr(key);
System.out.println("Pipeline mengirim permintaan");
try{
r1.get(); // Kesalahan terjadi karena klien belum mulai menerima respons.
}catch(Exception e){
System.out.println(" <<< Pipeline error: Klien belum mulai menerima respons. >>> ");
}
// Setelah pipeline mengirim semua permintaan, klien mulai menerima respons.
System.out.println("Permintaan terkirim. Mulai menerima respons");
p2.sync();
System.out.println("Pipeline menerima respons: " + r1.get());
System. out. println ("Pipeline menerima respons: " + r2.get ());
System. out. println ("Pipeline menerima respons: " + r3.get ());
System. out. println ("Pipeline menerima respons: " + r4.get ());
System. out. println ("Pipeline menerima respons: " + r5.get ());
jedis.close();
}
}Setelah Anda memasukkan endpoint dan kata sandi yang benar untuk terhubung ke instans Tair (Redis OSS-compatible) dan menjalankan kode Java di atas, keluaran berikut akan ditampilkan:
----- Metode 1 -----
Pipeline mengirim permintaan
Pipeline mengirim permintaan
Pipeline mengirim permintaan
Pipeline mengirim permintaan
Pipeline mengirim permintaan
Setelah pipeline mengirim semua permintaan, klien mulai menerima respons.
Pipeline menerima respons: 1
Pipeline menerima respons: 2
Pipeline menerima respons: 3
Pipeline menerima respons: 4
Pipeline menerima respons: 5
----- Metode 2 -----
Pipeline mengirim permintaan
Pipeline mengirim permintaan
Pipeline mengirim permintaan
Pipeline mengirim permintaan
Pipeline mengirim permintaan
<Pipeline error: Klien belum mulai menerima respons>
Setelah pipeline mengirim semua permintaan, klien mulai menerima respons.
Pipeline menerima respons: 1
Pipeline menerima respons: 2
Pipeline menerima respons: 3
Pipeline menerima respons: 4
Pipeline menerima respons: 5