ข้ามไปยังเนื้อหา

Pipelines

ทุกคำสั่ง Redis มี round-trip: client ส่งคำสั่ง รอ reply แล้วจึงส่งคำสั่งถัดไป บน network ที่มี latency แม้เพียงเล็กน้อย นี่สะสมได้รวดเร็ว

Pipelining ให้ client ส่งชุดคำสั่งในการเขียนครั้งเดียวโดยไม่ต้องรอ reply ของแต่ละคำสั่ง server ประมวลผลตามลำดับและส่ง reply ทั้งหมดกลับมาพร้อมกัน ผลลัพธ์คือ round-trip เดียวแทนที่จะเป็น N round-trips

# ไม่มี pipelining: 3 round-trips
127.0.0.1:6379> SET a 1
OK
127.0.0.1:6379> SET b 2
OK
127.0.0.1:6379> SET c 3
OK
# มี pipelining: 1 round-trip ผลลัพธ์เหมือนกัน

Redis client library ส่วนใหญ่เปิด pipelining โดยตรง ตัวอย่างใน Node.js (ioredis):

Terminal window
const pipeline = redis.pipeline();
pipeline.set('a', 1);
pipeline.set('b', 2);
pipeline.set('c', 3);
const results = await pipeline.exec();

redis-cli มาพร้อม flag --pipe ที่รับ Redis protocol (RESP) จาก stdin และส่งเป็น pipeline:

Terminal window
# สร้าง RESP inline และส่งผ่าน pipe ไปยัง Redis
printf "*3\r\n\$3\r\nSET\r\n\$2\r\nk1\r\n\$5\r\nhello\r\n*3\r\n\$3\r\nSET\r\n\$2\r\nk2\r\n\$5\r\nworld\r\n" \
| redis-cli --pipe

เหมาะสำหรับ bulk import: เครื่องมืออย่าง redis-cli --pipe สามารถโหลดได้นับล้าน key ในเวลาไม่กี่วินาทีโดยส่ง batch ขนาดใหญ่ผ่าน connection เดียว

คุณยังสามารถสร้างไฟล์คำสั่งและส่งผ่าน pipe:

Terminal window
# commands.txt มีคำสั่ง redis-cli หนึ่งบรรทัดต่อหนึ่งคำสั่ง
cat commands.txt | redis-cli --pipe

Pipeline และ transaction มักถูกสับสน ตารางด้านล่างชี้แจงความแตกต่าง:

คุณสมบัติPipelineTransaction (MULTI/EXEC)
Round-tripsหนึ่ง (หรือน้อย)หนึ่งต่อคำสั่ง + EXEC
Atomicityไม่มี — client อื่นสามารถแทรกได้ใช่ — ไม่มีการขัดจังหวะ
Rollbackไม่มีไม่มี
Use caseThroughput / bulk loadการเขียนกลุ่มที่ปลอดภัย

Pipeline คือ network optimization Transaction คือ atomicity guarantee คุณสามารถรวมทั้งสองได้: client library หลายตัวให้คุณส่งบล็อก MULTI/EXEC ภายใน pipeline เพื่อได้ประโยชน์ทั้งคู่

SET a 1
SET b 2
SET c 3
MGET a b c
ตัวเลือกBenefitCost
Pipeline (batch หลายคำสั่งใน request เดียว)ลด network round-trip เหลือแทบ 1 ครั้ง เพิ่ม throughput ได้มากสำหรับ bulk operationไม่มี atomicity — client อื่นสามารถแทรกคำสั่งระหว่างคำสั่งใน pipeline ได้
redis-cli --pipe สำหรับ bulk importโหลดข้อมูลจำนวนล้าน key ได้ในไม่กี่วินาที ผ่าน connection เดียวต้องสร้าง RESP protocol เองหรือใช้ command file ดีบักยากกว่าคำสั่งทีละบรรทัด
รวม MULTI/EXEC ไว้ใน pipelineได้ทั้ง round-trip น้อยและ atomicity guaranteeเพิ่มความซับซ้อนของโค้ด client ต้องเข้าใจทั้งสองแนวคิดควบคู่กัน
  • คิดว่า pipeline ให้ atomicity เหมือน transaction — pipeline เป็นแค่ network optimization ที่รวมคำสั่งไปในการเขียนครั้งเดียว client อื่นยังสามารถรันคำสั่งของตัวเองแทรกระหว่างคำสั่งใน pipeline ได้ ถ้าต้องการ atomicity ต้องห่อด้วย MULTI/EXEC
  • ส่ง pipeline ขนาดใหญ่เกินไปในครั้งเดียว — batch ที่ใหญ่มากอาจทำให้ memory buffer ทั้งฝั่ง client และ server พองขึ้นชั่วคราว ควรแบ่งเป็น batch ขนาดพอเหมาะ (เช่น หลักพันคำสั่งต่อ pipeline)
  • ไม่ตรวจสอบผลลัพธ์แต่ละคำสั่งใน pipeline — pipeline คืน array ของผลลัพธ์ตามลำดับคำสั่ง หากมีคำสั่งใดผิดพลาดระหว่างทาง คำสั่งอื่นยังรันต่อ ต้อง loop ตรวจ error ในผลลัพธ์เอง ไม่ใช่ assume ว่าทั้ง batch สำเร็จหมด

💡 ตัวอย่างจากของจริง

Bulk data import job ทั่วไป — ใช้ redis-cli --pipe หรือ client library pipelining เพื่อโหลดข้อมูล seed หรือ migrate ข้อมูลนับล้าน key เข้า Redis โดยลด round-trip จากนับล้านครั้งเหลือเพียงไม่กี่ batch

Analytics/logging pipeline — ระบบที่ต้องเขียน event จำนวนมากต่อวินาทีมักรวมคำสั่ง SET/INCR/ZADD เป็น pipeline เพื่อให้ throughput สูงพอสำหรับ traffic ที่มี volume สูง

ประโยชน์หลักของ pipelining ใน Redis คืออะไร?
เมื่อใช้ pipeline คำสั่งของ client อื่นสามารถแทรกกับคำสั่งใน pipeline ได้หรือไม่?
flag ของ redis-cli ที่เปิด pipe mode สำหรับ bulk import คืออะไร?
เพื่อให้ได้ทั้ง round-trip ที่น้อยลงและ atomicity คุณควร: