DEV Community

TOT
TOT

Posted on

Kiến trúc hệ thống CRM xử lý dữ liệu tải cao cho ngành ô tô

Các chiến dịch tiếp thị xe hơi thường tạo ra lượng truy cập và yêu cầu tư vấn khổng lồ trong thời gian ngắn. Khi hàng ngàn dữ liệu khách hàng đổ về cùng lúc từ Meta Ads, Google Ads hoặc Landing Page, các hệ thống quản trị monolith truyền thống rất dễ rơi vào trạng thái quá tải kết nối.

Sự trễ ca trong quá trình xử lý dữ liệu làm giảm hơn 80% tỷ lệ chuyển đổi hợp đồng. Trong ngành bán lẻ xe, thông tin khách hàng không phải là một bản ghi tĩnh mà là một trạng thái động gắn liền với dữ liệu tồn kho theo số VIN và lịch xe demo của showroom.

Để giải quyết triệt để bài toán nghẽn luồng dữ liệu và đáp ứng độ trễ dưới 1 giây, việc thiết lập hạ tầng CRM cho showroom ô tô dựa trên kiến trúc Event-Driven kết hợp Caching Layer là giải pháp kỹ thuật tối ưu cho các hệ thống quy mô lớn.


Điểm nghẽn hạ tầng của các hệ thống CRM truyền thống

Hầu hết phần mềm quản trị quan hệ khách hàng đóng gói sẵn được thiết kế dựa trên mô hình CRUD cơ bản và cơ sở dữ liệu quan hệ đồng bộ. Mô hình này nhanh chóng bộc lộ các rào cản kỹ thuật khi áp dụng vào mô hình showroom xe hơi.

Latency trong luồng Ingestion và rủi ro nghẽn HTTP Connection

Khi chiến dịch ra mắt dòng xe mới được kích hoạt, hệ thống phải nhận hàng trăm request Webhook mỗi giây. Nếu ứng dụng xử lý việc xác thực token, parse payload và ghi trực tiếp vào cơ sở dữ liệu chính (Write Database) trên cùng một HTTP thread đồng bộ, cạn kiệt Connection Pool là điều khó tránh khỏi.

Hậu quả là các API Gateway bên phía Meta hoặc Google sẽ nhận mã lỗi HTTP 500 hoặc Timeout, dẫn đến mất mát dữ liệu khách hàng tiềm năng.

Xung đột dữ liệu Tồn kho VIN và Lịch lái thử (Race Conditions)

Một chiếc xe với số VIN cụ thể hoặc một xe demo chạy thử chỉ có thể được đặt cọc hoặc đặt lịch bởi một tư vấn bán hàng tại một thời điểm. Khi nhiều tư vấn bán hàng cùng thao tác đặt giữ xe cho khách trên ứng dụng di động, các truy vấn ghi đồng thời dễ dẫn đến tình trạng Race Condition.

Nếu chỉ dùng cơ chế Row-level Locking của cơ sở dữ liệu quan hệ, toàn bộ hệ thống sẽ bị giảm hiệu năng truy vấn do hiện tượng Lock Contention.

Kiến trúc Event-Driven và Xử lý Bất đồng bộ cho CRM Bán lẻ Xe

Để đảm bảo hệ thống luôn sẵn sàng xử lý tải cao với thời gian phản hồi API dưới 100ms, toàn bộ luồng tiếp nhận và phân bổ dữ liệu cần được tách rời (Decoupled) thành các dịch vụ độc lập.

[Ad Platforms / Webhooks] 
       │
       ▼
[Edge API Ingestion Gateway]
       │
       ▼
[Message Queue (Kafka / RabbitMQ)]
       │
       ▼
[Lead Distribution Worker Engine]
       │
       ▼
[Redis Cache] ──► [PostgreSQL / Write DB]
Enter fullscreen mode Exit fullscreen mode

1. Luồng tiếp nhận Lead qua Message Queue (Kafka / RabbitMQ)

API Ingestion Gateway được xây dựng cực nhẹ (Lightweight Edge Service). Nhiệm vụ duy nhất của Gateway là nhận HTTP POST Payload, xác thực chữ ký HMAC và đẩy ngay lập tức một Event dạng JSON vào Message Queue như Apache Kafka hoặc RabbitMQ.

Ngay sau khi Event được ghi vào Queue, Gateway trả về HTTP 200 OK cho phía dịch vụ quảng cáo. Toàn bộ quá trình này diễn ra trong thời gian dưới 50ms.

2. Thuật toán Phân bổ Lead tự động theo trọng số (Weighted Routing)

Một nhóm các Worker Service sẽ liên tục tiêu thụ (Consume) các Event từ Message Queue và thực thi logic phân bổ. Thuật toán phân bổ tự động tính toán các tham số thực tế:

  • Geofencing: Định vị vị trí địa lý của khách hàng để gán về đúng chi nhánh showroom gần nhất.

  • Trạng thái làm việc của Sale: Trích xuất trạng thái Online/Offline và số lượng lead đang xử lý của từng nhân viên từ Redis.

  • SLA Timeout: Nếu nhân viên không bấm xác nhận nhận lead trong 180 giây, Worker sẽ kích hoạt Event chuyển tiếp lead lên cấp quản lý.

So sánh Mô hình Kiến trúc Monolith và Event-Driven Microservices

Việc nâng cấp hạ tầng từ kiến trúc đồng bộ sang kiến trúc bất đồng bộ giúp thay đổi hoàn toàn chỉ số đo lường hiệu năng hệ thống.

Tiêu chí kỹ thuật Kiến trúc Monolith CRUD Đồng bộ Kiến trúc Event-Driven Microservices
Mức độ chịu tải Ingestion Giới hạn bởi Database Connection Pool Mở rộng theo chiều ngang (Horizontal Scale) qua Message Queue
Thời gian phản hồi Webhook 800ms - 3000ms (Phụ thuộc ghi DB) Dưới 50ms (Chỉ xác thực và push Queue)
Cơ chế xử lý Race Condition DB Transaction Lock (Dễ nghẽn Thread) Distributed Lock trên In-memory Cache (Redis)
Khả năng cách ly sự cố Một lỗi DB làm gián đoạn toàn bộ hệ thống Queue lưu trữ Message, Worker tự khôi phục khi gặp sự cố
Quản lý dữ liệu tồn kho VIN Query liên tục vào Relational Database Cập nhật State Machine qua Redis Pub/Sub
Phân tích báo cáo Real-time Chạy SQL Aggregate trực tiếp trên DB chính Stream dữ liệu sang OLAP Engine (ClickHouse)

Kỹ thuật Lock Tồn kho Xe theo mã VIN bằng Redis Distributed Lock

Quản lý tài sản giá trị cao yêu cầu độ chính xác tuyệt đối về mặt dữ liệu. Để xử lý bài toán giữ xe hoặc đặt lịch xe demo đồng thời, kỹ sư hệ thống sử dụng thuật toán Redlock hoặc Redis Primitives để tạo Distributed Lock.

Khi tư vấn bán hàng gửi yêu cầu khóa một mã VIN để lập hợp đồng:

Key: lock:vin:1FA6P8CF0R5100000
TTL: 900 seconds
Command: SET lock:vin:[VIN_ID] [REQUEST_ID] NX PX 900000
Enter fullscreen mode Exit fullscreen mode

Hệ thống sẽ kiểm tra xem Key này đã tồn tại trên In-Memory Cache chưa. Nếu lệnh trả về success, giao dịch đặt xe được chấp nhận và Worker sẽ ghi nhận trạng thái tạm khóa. Các truy vấn khác đến cùng mã VIN trong khoảng thời gian này sẽ bị từ chối ngay tại tầng Cache mà không cần tiêu tốn tài nguyên truy vấn vào PostgreSQL.

Kiến trúc CRM cho showroom ô tô xử lý dữ liệu tải cao

Các chiến dịch tiếp thị xe hơi thường tạo ra lượng truy cập và yêu cầu tư vấn khổng lồ trong thời gian ngắn. Khi hàng ngàn dữ liệu khách hàng đổ về cùng lúc từ Meta Ads, Google Ads hoặc Landing Page, các hệ thống quản trị monolith truyền thống rất dễ rơi vào trạng thái quá tải kết nối.

Sự trễ ca trong quá trình xử lý dữ liệu làm giảm hơn 80% tỷ lệ chuyển đổi hợp đồng. Trong ngành bán lẻ xe, thông tin khách hàng không phải là một bản ghi tĩnh mà là một trạng thái động gắn liền với dữ liệu tồn kho theo số VIN và lịch xe demo của showroom.

Thiết kế Schema PostgreSQL và Tối ưu Index cho Query Tải cao

Để đáp ứng tính linh hoạt của ngành bán lẻ ô tô khi mỗi thương hiệu xe có các thông số kỹ thuật khác nhau, mô hình lưu trữ Hybrid giữa Relational Table và JSONB trong PostgreSQL là lựa chọn phù hợp.

Thiết kế Bảng Lead và Tồn kho VIN

Bảng lưu trữ thông tin khách hàng sử dụng các cột cố định cho các trường dữ liệu bắt buộc và cột JSONB cho các thuộc tính tùy biến của chiến dịch tiếp thị.

SQL

CREATE TABLE leads (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    dealership_id UUID NOT NULL,
    assigned_sales_id UUID,
    full_name VARCHAR(100) NOT NULL,
    phone_number VARCHAR(20) NOT NULL,
    pipeline_state VARCHAR(30) NOT NULL,
    metadata JSONB,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
Enter fullscreen mode Exit fullscreen mode

Tối ưu hóa Partial Index cho Lead đang hoạt động

Các truy vấn phân bổ và quét SLA chỉ quan tâm đến các lead đang trong quá trình xử lý, không cần quét qua hàng triệu bản ghi đã đóng deal hoặc hủy bỏ. Tạo Partial Index giúp tiết kiệm bộ nhớ RAM và tăng tốc độ truy vấn:

SQL

CREATE INDEX idx_active_leads_processing 
ON leads (dealership_id, assigned_sales_id) 
WHERE pipeline_state IN ('NEW', 'ASSIGNED', 'CONTACTED');
Enter fullscreen mode Exit fullscreen mode

Index này giúp giảm đáng kể kích thước Index Tree, đảm bảo các câu lệnh SELECT của Worker Engine luôn thực thi trong thời gian tính bằng milisecond.

Câu hỏi thường gặp

Làm sao để đảm bảo thứ tự xử lý sự kiện trong Message Queue khi nhận Lead?

Sử dụng cơ chế Partitioning trong Apache Kafka với Message Key là dealership_id hoặc phone_number. Tất cả sự kiện liên quan đến cùng một khách hàng sẽ luôn đi vào cùng một Partition và được xử lý theo đúng thứ tự FIFO.

Tại sao nên dùng Partial Index thay vì B-Tree Index thông thường cho bảng Lead?

Bảng Lead chứa dung lượng lớn các bản ghi lịch sử đã hoàn tất giao dịch. Partial Index chỉ đánh chỉ mục cho các bản ghi đang ở trạng thái active, giúp tiết kiệm bộ nhớ Cache RAM và duy trì tốc độ đọc/ghi cao nhất cho database.

Làm thế nào để đồng bộ dữ liệu giữa Redis Cache và PostgreSQL khi có sự cố ngắt kết nối?

Hệ thống sử dụng mô hình Write-Behind Cache (Write-Back). Mọi thay đổi trạng thái được ghi vào Redis trước, sau đó một Background Worker sẽ đồng bộ dữ liệu xuống PostgreSQL thông qua các giao dịch theo lô (Batch Processing).

Top comments (0)