การสร้างไปป์ไลน์วิเคราะห์การฉ้อโกงแบบเรียลไทม์
แนวทางสถาปัตยกรรม: รับข้อมูล 50K อีเวนต์ต่อวินาที เสริมด้วย smart signals และให้คะแนนความเสี่ยงภายในไม่เกิน 10ms ด้วยสตรีมมิงเอนจินของเรา
การประมวลผล fingerprint 50,000 อีเวนต์ต่อวินาที เสริมแต่ละอีเวนต์ด้วย smart signals และคืนคะแนนความเสี่ยงภายในไม่เกิน 10 มิลลิวินาที ต้องอาศัยสถาปัตยกรรมแบบสตรีมมิงที่ออกแบบมาอย่างพิถีพิถัน บทความนี้จะพาไล่ดูไปป์ไลน์ของเราตั้งแต่การรับข้อมูลจนถึงการตัดสินใจ
เลเยอร์รับข้อมูล (Ingestion Layer)
อีเวนต์เข้ามาในรูปแบบ HTTPS POST request จาก JavaScript agent ของเราที่ทำงานอยู่ในเบราว์เซอร์ของผู้เข้าชม แต่ละอีเวนต์บรรจุ payload ของสัญญาณที่เข้ารหัสไว้ — โดยทั่วไปเป็นข้อมูลอัดแน่นขนาด 8-12KB ที่ครอบคลุมสัญญาณเบราว์เซอร์กว่า 130+ รายการ เซิร์ฟเวอร์ edge ของเราทำหน้าที่ terminate TLS ตรวจสอบลายเซ็นของ request และส่งต่อ payload ไปยังไปป์ไลน์ประมวลผล
เราใช้การดีพลอยแบบหลายภูมิภาค (multi-region) โดยวางเซิร์ฟเวอร์ edge ไว้ร่วมตำแหน่งกับโหนด CDN ของลูกค้าเรา ซึ่งช่วยให้เวลาไป-กลับของเครือข่าย (round-trip) อยู่ต่ำกว่า 20ms สำหรับ 95% ของ request ทั่วโลก เซิร์ฟเวอร์ edge เป็นเซอร์วิส Go แบบ stateless ที่ทำงานอยู่หลัง load balancer และขยายสเกลตามแนวนอน (horizontal scaling) ตามปริมาณ request
การสกัดสัญญาณ (Signal Extraction)
สเตจประมวลผลแรกทำหน้าที่ถอดรหัสและ parse payload ของสัญญาณ แต่ละสัญญาณจะถูกสกัด ตรวจสอบความถูกต้อง และกำหนดชนิด (type) ค่า hash ของ Canvas จะถูกตรวจสอบเทียบกับค่าที่เป็นไปไม่ได้ที่รู้จัก (ซึ่งบ่งชี้ว่ามีการบล็อก Canvas หรือการปลอมแปลง) พารามิเตอร์ WebGL จะถูกตรวจสอบไขว้เพื่อความสอดคล้อง และคุณสมบัติของ Navigator จะถูกตรวจเทียบกับชุดค่าที่ถูกต้องซึ่งรู้จัก
สเตจนี้ยังทำ normalization ของสัญญาณด้วย สตริง user agent จะถูก parse เป็นองค์ประกอบที่มีโครงสร้าง (เบราว์เซอร์ เวอร์ชัน OS อุปกรณ์) ขนาดหน้าจอจะถูกทำให้เป็นมาตรฐานเพื่อรองรับการปรับสเกล DPI และค่า offset ของ timezone จะถูกตรวจสอบเทียบกับข้อมูล geolocation ของ IP
การเสริมด้วย Smart Signals (Smart Signals Enrichment)
สัญญาณที่สกัดได้จะถูกเสริมด้วยการวิเคราะห์ Smart Signals — เลเยอร์ข่าวกรอง (intelligence) ฝั่งเซิร์ฟเวอร์ของเรา ซึ่งรวมถึงการตรวจจับ incognito (เปรียบเทียบรูปแบบสัญญาณกับลายเซ็นของการเรียกดูแบบส่วนตัวที่รู้จัก) การตรวจจับ VPN (ตรวจไขว้ข้อมูล IP กับสัญญาณ timezone และ locale) การตรวจจับการดัดแปลงเบราว์เซอร์ (ระบุความไม่สอดคล้องที่บ่งชี้ถึงการปลอมสัญญาณ) และการตรวจจับ virtual machine (จดจำโปรไฟล์ฮาร์ดแวร์ที่เกี่ยวข้องกับ VMware, VirtualBox และ cloud VM)
แต่ละ smart signal ถูกคำนวณอย่างอิสระและให้ผลลัพธ์ทั้งค่า boolean และคะแนนความเชื่อมั่น (confidence score) สเตจการเสริมข้อมูลนี้เพิ่มสัญญาณอีก 24 รายการให้กับแต่ละอีเวนต์ ทำให้ได้การประเมินภัยคุกคามที่ครอบคลุมเกินกว่าที่การเก็บข้อมูลฝั่งไคลเอนต์เพียงอย่างเดียวจะทำได้
เอนจินให้คะแนนความเสี่ยง (Risk Scoring Engine)
อีเวนต์ที่เสริมข้อมูลแล้วจะถูกส่งไปยังเอนจินให้คะแนนความเสี่ยงของเรา — โมเดล gradient-boosted decision tree ที่ฝึกจากอีเวนต์ที่มี label หลายล้านรายการ โมเดลจะพิจารณาสัญญาณดิบทั้งหมด 130+ รายการ, smart signals 24 รายการ และฟีเจอร์ที่ได้จากการคำนวณอีกหลายอย่าง ได้แก่ metric ด้านความเร็ว (velocity — มีกี่อีเวนต์จากอุปกรณ์นี้ในช่วง 5 นาที, 1 ชั่วโมง และ 24 ชั่วโมงที่ผ่านมา) รูปแบบพฤติกรรมในอดีต และคะแนนชื่อเสียงของเครือข่าย (network reputation)
โมเดลจะให้ผลลัพธ์เป็นคะแนนความเสี่ยงระหว่าง 0 ถึง 100 พร้อมกับปัจจัยหลักที่มีผลมากที่สุด ตัวอย่างเช่น คะแนน 85 อาจมาพร้อมปัจจัยอย่าง "ตรวจพบ VPN," "โหมด incognito," และ "velocity สูง — 47 อีเวนต์ใน 5 นาที" ความสามารถในการอธิบายผล (explainability) นี้สำคัญยิ่งสำหรับนักวิเคราะห์การฉ้อโกงที่ต้องเข้าใจว่าทำไมอีเวนต์หนึ่งจึงถูกตั้งค่าสถานะ (flag)
เลเยอร์จัดเก็บและคิวรี (Storage and Query Layer)
อีเวนต์ทั้งหมดจะถูกบันทึกลง ClickHouse — ฐานข้อมูลแบบ columnar ที่ปรับแต่งมาเพื่อคิวรีเชิงวิเคราะห์บนชุดข้อมูลขนาดใหญ่ ClickHouse รองรับปริมาณการเขียนของเรา (50K อีเวนต์ต่อวินาที) ได้อย่างสบายๆ และการจัดเก็บแบบ columnar ช่วยให้คิวรีเชิงวิเคราะห์บนข้อมูลหลายพันล้านแถวเสร็จได้ในเวลาต่ำกว่าหนึ่งวินาที
เราใช้กลยุทธ์การเก็บรักษาข้อมูลแบบหลายชั้น (multi-tier retention) ข้อมูลร้อน (hot data — 7 วันล่าสุด) ถูกจัดเก็บบน NVMe SSD เพื่อให้คิวรีตอบสนองในเวลาต่ำกว่า 100ms ข้อมูลอุ่น (warm data — 7-90 วัน) อยู่บน SSD มาตรฐาน ส่วนข้อมูลเย็น (cold data — 90 วันขึ้นไป) จะถูกบีบอัดและย้ายไปยัง object storage ซึ่งยังคิวรีได้แต่มี latency สูงกว่า
Kafka ในฐานะแกนหลัก
Apache Kafka เชื่อมไปป์ไลน์เข้าด้วยกัน ทุกสเตจอ่านและเขียนไปยัง topic ของ Kafka เลเยอร์รับข้อมูลเขียนอีเวนต์ดิบ สเตจการสกัดสัญญาณอ่านอีเวนต์ดิบและเขียนอีเวนต์ที่สกัดแล้ว สเตจการเสริมด้วย Smart Signals อ่านอีเวนต์ที่สกัดแล้วและเขียนอีเวนต์ที่เสริมข้อมูลแล้ว และเอนจินให้คะแนนความเสี่ยงอ่านอีเวนต์ที่เสริมข้อมูลแล้วและเขียนอีเวนต์ที่ให้คะแนนแล้ว
สถาปัตยกรรมนี้ให้ข้อได้เปรียบหลายอย่าง: แต่ละสเตจสามารถขยายสเกลได้อิสระ ความล้มเหลวในสเตจหนึ่งไม่กระทบสเตจอื่น และเราสามารถ replay อีเวนต์ผ่านสเตจใดก็ได้เพื่อการดีบักหรือประมวลผลซ้ำ consumer group ของ Kafka ช่วยให้ประมวลผลแบบขนานภายในแต่ละสเตจได้ และ exactly-once semantics ของมันรับประกันว่าไม่มีอีเวนต์ใดถูกประมวลผลซ้ำสองครั้งหรือสูญหาย
งบเวลา Latency (Latency Budget)
เป้าหมาย latency แบบ end-to-end ของเราคือ 10ms นับจากช่วงเวลาที่ payload สัญญาณที่เสริมข้อมูลแล้วมาถึงไปป์ไลน์ประมวลผล จนถึงช่วงเวลาที่คืนคะแนนความเสี่ยงออกไป งบเวลาแบ่งออกดังนี้: การสกัดสัญญาณใช้เวลา 1-2ms การเสริมด้วย Smart Signals ใช้ 3-4ms การให้คะแนนความเสี่ยงใช้ 2-3ms และการทำ serialization กับการตอบกลับใช้ 1-2ms ส่วนการ hop ระหว่างสเตจของ Kafka เพิ่มเวลาไม่ถึง 1ms ในการดีพลอยแบบวางร่วมตำแหน่ง (co-located) ของเรา
การทำให้อยู่ในงบเวลานี้ได้อย่างสม่ำเสมอที่ 50K อีเวนต์ต่อวินาที ต้องอาศัยการปรับแต่งอย่างพิถีพิถันในทุกสเตจ เราใช้ memory pool ที่จองไว้ล่วงหน้า (pre-allocated) การทำ serialization แบบ zero-copy และการเขียน ClickHouse แบบ batch โมเดลให้คะแนนความเสี่ยงถูกคอมไพล์เป็นโค้ดเนทีฟด้วย ONNX Runtime เพื่อกำจัด overhead ของ Python interpreter
Mark ใช้เวลาสองสัปดาห์ในการทำ profiling ไปป์ไลน์ก่อนจะเจอคอขวดในเลเยอร์ lookup แบบกระจาย (distributed lookup) ของเรา — mutex เดี่ยวตัวหนึ่งกำลังทำ lookup แบบ serialize ข้าม goroutine ทั้งหมด หลังจากเปลี่ยนมาใช้ดีไซน์ล็อกแบบ sharded ค่า p99 ก็ลดจาก 48ms เหลือ 9ms บางครั้งวิธีแก้ก็ง่ายจนน่าอายเมื่อคุณหามันเจอแล้ว