การออกแบบเครื่องคิดค่าบริการแบบ idempotent
ระบบคิดค่าบริการมักล้มเหลวในแบบที่แพงที่สุด คือเงียบ ๆ ด้วยการเรียกเก็บซ้ำหรือทำเรกคอร์ดหาย ทางแก้ไม่ใช่การ retry ให้มากขึ้น แต่คือทำให้ทุกการทำงานปลอดภัยต่อการทำซ้ำ
รูปร่างของปัญหา
เครื่องคิดค่าบริการเปลี่ยนเหตุการณ์ให้กลายเป็นเงิน ในธุรกิจโทรคมนาคมนั่นหมายถึงเรกคอร์ดรายละเอียดการโทร (CDR): วันละหลายพันล้านรายการ มาถึงไม่เรียงลำดับ บางครั้งมาซ้ำ บางครั้งก็หายไป โหมดความล้มเหลวที่แพงที่สุด ไม่ใช่การล่ม แต่เป็นความเงียบ ที่ batch ถูกลองใหม่แล้วเรียกเก็บเงินลูกค้าซ้ำ หรือ partition ที่หล่นหาย ทำให้รายได้สูญไปโดยไม่มีใครสังเกตเป็นเดือน
การลองใหม่ไม่ได้แก้ปัญหานี้ ยิ่งลองใหม่มากยิ่งแย่ลง คำตอบที่ยั่งยืนเพียงทางเดียวคือทำให้ทุกการเขียน ปลอดภัยต่อการทำซ้ำ เพื่อให้การเล่นเรกคอร์ดเดิมซ้ำไม่เปลี่ยนแปลงอะไรเลย
“ระบบที่ idempotent ไม่กลัวการ retry เพราะมันถูกสร้างมาให้เล่นซ้ำได้”
graph LR
A[CDR sources] --> B(["Kafka ingest"])
B --> C[Rating engine]
C --> D{{"Idempotency store"}}
C --> E[("Ledger")]
E --> F[Reconciliation]
F -. verifies .-> E
ภาพที่ 1 / การไหลของข้อมูลการคิดค่าบริการ - ทุกเรกคอร์ดมีคีย์กำกับ ledger และการกระทบยอดต้องตรงกัน ไม่เช่นนั้น pipeline จะหยุด
ทำให้การเขียนเป็น idempotent
ทั้งหมดนี้ตั้งอยู่บนคีย์กันซ้ำที่ได้จากตัวเรกคอร์ดเอง ไม่ใช่จากเวลาที่ประมวลผล การ upsert ลง ledger ใช้คีย์นี้ ดังนั้นความพยายามครั้งที่สองจะพบผลลัพธ์เดิมและคืนค่ากลับโดยไม่เปลี่ยนแปลง
public RatingResult rate(CallDetailRecord cdr) {
// The dedup key turns a replay into a no-op, not a double charge.
String key = cdr.accountId() + ":" + cdr.eventId();
return ledger.upsert(key, () -> {
Money amount = tariff.price(cdr);
return new RatingResult(key, amount, cdr.timestamp());
});
}
การตั้งค่าช่วยให้สองฝั่งซื่อสัตย์ต่อกัน คีย์อยู่นานพอจะครอบคลุมช่วงการเล่นซ้ำที่เกิดขึ้นจริง และการกระทบยอด จะไม่ยอมปิดรายการใดที่อธิบายไม่ได้
rating:
idempotency:
store: cassandra
ttl: 90d # keep keys long enough to cover replays
reconcile:
interval: 60s
on_mismatch: halt # never settle a record we cannot explain
สิ่งที่เราวัดได้
เครื่องนี้ทำงานในโปรดักชันข้ามหลายตลาดมากว่าหนึ่งปี:
- 4B เรกคอร์ดที่คิดค่าบริการต่อวัน กระทบยอดครบวงจร
- 0 การรั่วไหลของรายได้ เมื่อเทียบกับระบบต้นทาง
- 60s รอบการกระทบยอด หยุดทันทีเมื่อไม่ตรงกัน
- 1 จอ คู่มือที่ทีม on-call ใช้งานจริง
ไม่มีอะไรหวือหวา มันคือเวอร์ชันที่น่าเบื่อแต่พิสูจน์ได้ ซึ่งเป็นเหตุผลว่าทำไมมันไม่เคยปลุกใครตอนตีสาม นั่นคือคำชมสูงสุดที่ระบบคิดค่าบริการจะได้รับ