← Tất cả dự án

IDEA Technology · R&D

VendAD

CMS quảng cáo số cho máy bán hàng

Vai trò
Phụ trách end-to-end
Liên kết
Công nghệ
  • ASP.NET Core 8
  • EF Core
  • PostgreSQL
  • SQL Server
  • Redis
  • RabbitMQ
  • SignalR
  • MediatR
  • Flutter · Android TV
  • Docker
  • GitHub Actions
  • k6

Tổng quan

Nền tảng quảng cáo cho máy bán hàng tự động do tôi phụ trách end-to-end: portal ASP.NET Core MVC, backend và database, ứng dụng phát nội dung Flutter cho Android TV, và hạ tầng triển khai giữ cả đội màn hình luôn đồng bộ.

Những gì tôi làm

Thiết kế hệ thống

Cache invalidation hướng sự kiện

Khi nội dung được duyệt hoặc sửa, một message RabbitMQ được publish. Background worker consume và chỉ invalidate đúng các Redis key liên quan, nên mọi màn hình nhận thay đổi trong vài giây mà không cần polling.

Redis distributed lock với Lua

SETNX kết hợp Lua script tuần tự hóa các cập nhật nội dung và rebuild cache đồng thời giữa nhiều instance, có lease TTL để worker bị crash không bao giờ làm kẹt cả hệ thống.

Một codebase, hai database

EF Core với migration không phụ thuộc provider cho phép cùng hệ thống chạy trên PostgreSQL hoặc SQL Server bằng cấu hình, được kiểm chứng bằng Testcontainers cho cả hai trong CI.

Pipeline kiểm tra video

File upload đi qua bước kiểm tra header bằng ffprobe để loại sớm, rồi decode đầy đủ bằng FFmpeg theo chính sách codec, độ phân giải, bitrate và thời lượng trước khi lên màn hình.

Bài toán đã giải

  1. Vấn đềMàn hình ở nhiều địa điểm hiển thị nội dung cũ tới 10 phút sau khi admin cập nhật.

    Giải phápMỗi thay đổi nội dung phát ra sự kiện để background worker invalidate đúng Redis key. Độ trễ giảm từ khoảng 10 phút xuống dưới 3 giây.

  2. Vấn đềNhiều admin sửa cùng lúc làm cache lệch, hai màn hình có thể phát hai phiên bản khác nhau của cùng một chiến dịch.

    Giải phápCác thao tác ghi quan trọng được tuần tự hóa bằng Redis lock dùng Lua, có lease và tự hết hạn, cùng retry queue cho các lần acquire thất bại.

  3. Vấn đềVideo sai codec lọt tới thiết bị và lỗi khi phát.

    Giải phápKiểm tra hai bước: ffprobe để loại ngay, decode đầy đủ bằng FFmpeg cho an toàn, kèm thông báo lỗi chỉ rõ cách encode lại.

Hình ảnh

Bài học