2 điểm bởi GN⁺ 2025-10-31 | 1 bình luận | Chia sẻ qua WhatsApp
  • Benchmark hiệu năng publish/subscribe (pub-sub)queue của Postgres, cho thấy khả năng thay thế hệ thống messaging chỉ với một cơ sở dữ liệu duy nhất
  • Trên một node 4vCPU đơn lẻ, đạt 5.036 lượt ghi/giây và 25.183 lượt đọc/giây; trong môi trường sao chép 3 node vẫn duy trì thông lượng tương tự, với độ trễ end-to-end 186ms (p99)
  • Trên node lớn 96vCPU, đạt ghi 238MiB/s, đọc 1.16GiB/s, với mức sử dụng CPU dưới 10%, cho thấy vẫn còn nhiều dư địa xử lý
  • Trong bài test queue, node đơn cũng xử lý được 2.885 lượt/giây, còn trong môi trường sao chép là 2.397 lượt/giây, đủ hiệu năng cho quy mô của phần lớn doanh nghiệp
  • Chứng minh rằng thay vì dùng hệ thống phân tán phức tạp, một hạ tầng Postgres duy nhất vẫn có thể xử lý workload ở mức vài MB/s, nhấn mạnh cách tiếp cận thực dụng: “hãy dùng công nghệ đơn giản cho tới khi thực sự cần thứ khác”

Hai phe trong lựa chọn công nghệ

  • Ngành công nghệ được chia thành phe chạy theo từ khóa thời thượngphe dựa trên lẽ thường
    • Phe trước bị hấp dẫn bởi các thuật ngữ marketing như “real-time”, “mở rộng vô hạn”, “AI-based”
    • Phe sau coi trọng sự đơn giản và tính thực dụng, tránh độ phức tạp không cần thiết
  • Gần đây, hai xu hướng Small Dataphục hưng Postgres đang tiếp thêm sức mạnh cho phe thứ hai
    • Dữ liệu ngày càng nhỏ hơn, còn phần cứng ngày càng mạnh hơn
    • Postgres có thể thay thế nhiều giải pháp chuyên biệt chỉ với một hệ thống duy nhất (jsonb, pgvector, tsvector...)

Tổng quan benchmark

  • Mục tiêu: đo xem Postgres có thể mở rộng tới mức nào trong messaging pub/subxử lý queue
  • Môi trường thử nghiệm: AWS EC2 c7i.xlarge (4vCPU) và c7i.24xlarge (96vCPU)
  • So sánh ba cấu hình
    • Node đơn
    • Cụm sao chép 3 node
    • Một node đơn cỡ lớn

Kết quả benchmark Pub/Sub

  • Node đơn 4vCPU
    • Ghi 4.8MiB/s (5.036msg/s), đọc 24.6MiB/s (25.183msg/s), độ trễ 60ms (p99)
    • CPU sử dụng 60%, ghi đĩa 46MiB/s
  • Sao chép 3 node 4vCPU
    • Ghi 4.9MiB/s, đọc 24.5MiB/s, độ trễ 186ms (p99)
    • Giữ được thông lượng, chi phí hằng năm khoảng $11.514
  • Node đơn 96vCPU
    • Ghi 238MiB/s (243kmsg/s), đọc 1.16GiB/s (1.2Mmsg/s), độ trễ 853ms (p99)
    • CPU dưới 10%, nút thắt nằm ở tốc độ ghi trên mỗi partition
  • Kết luận: đủ sức cạnh tranh với Kafka ở workload quy mô nhỏ đến trung bình, và với cấu trúc đơn giản vẫn có thể xử lý ở mức hàng chục MB/s

Kết quả benchmark Queue

  • Triển khai queue đơn giản dựa trên SELECT FOR UPDATE SKIP LOCKED
  • Node đơn 4vCPU
    • 2.81MiB/s (2.885msg/s), độ trễ 17.7ms (p99), CPU 60%
  • Sao chép 3 node 4vCPU
    • 2.34MiB/s (2.397msg/s), độ trễ 920ms (p99), CPU 60%
  • Node đơn 96vCPU
    • 19.7MiB/s (20.144msg/s), độ trễ 930ms (p99), CPU 40~60%
  • Chỉ với node đơn cũng có thể đáp ứng nhu cầu thông lượng queue của phần lớn doanh nghiệp

Khi nào nên dùng Postgres

  • Trong đa số trường hợp, chọn Postgres làm mặc định là hợp lý
    • Có thể debug, chỉnh sửa và join message bằng SQL
    • Vận hành đơn giản hơn và dễ bảo trì hơn so với Kafka
  • Kafka được tối ưu cho hiệu năng rất cao, nhưng với workload nhỏ thì đó là lựa chọn quá tay
  • Trích dẫn lời cảnh báo của Donald Knuth: “tối ưu hóa quá sớm là gốc rễ của mọi điều xấu
    • Ở mức vài MB/s, Postgres là đủ

Cách tiếp cận MVI

  • Minimum Viable Infrastructure: xây dựng hệ thống tối thiểu bằng những công nghệ mà tổ chức đã quen thuộc
    • Postgres được dùng rộng rãi và dễ tuyển người có kinh nghiệm
    • Càng ít thành phần thì càng giảm rủi ro sự cố và gánh nặng vận hành
  • Việc đưa thêm công nghệ không cần thiết sẽ tạo ra overhead ở cấp độ tổ chức
    • Tăng chi phí học tập, giám sát, triển khai và vận hành

Bàn về khả năng mở rộng

  • Postgres thực sự có thể mở rộng
    • OpenAI hiện vẫn sử dụng Postgres dựa trên một single write instance
    • Vẫn vận hành ổn định ở quy mô hàng trăm triệu người dùng
  • Phần lớn doanh nghiệp tăng trưởng với tốc độ vừa phải, nên còn nhiều năm trước khi buộc phải thay công nghệ
  • “Thiết kế để phòng trường hợp bùng nổ viral” là một dạng overdesign quá mức
    • Tác giả ví điều này như “mua ampli Marshall chỉ để chơi mở màn cho Coldplay”

Kết luận

  • “Hãy dùng Postgres cho tới khi nó gãy”
    • Công nghệ đơn giản vẫn có thể mang lại hiệu năng rất cao
    • Triển khai hệ thống phân tán phức tạp khi chưa cần là không hiệu quả
    • Kết hợp với phần cứng hiện đại, Postgres là một lựa chọn thực dụng có thể gánh được phần lớn workload

1 bình luận

 
GN⁺ 2025-10-31
Ý kiến Hacker News
  • Việc áp dụng nguyên tắc Pareto cho mọi tình huống là một cách diễn giải sai
    Nói rằng Postgres xử lý được 80% use case của Kafka với 20% công sức là một khẳng định không có cơ sở
    Nguyên tắc Pareto chỉ có ý nghĩa trong những tình huống xuất hiện phân phối lũy thừa
    Chỉ cần nói rằng Postgres bao phủ đủ nhiều use case, ổn định và là công cụ đã được kiểm chứng là được

    • Tuy vậy cũng có ý kiến cho rằng bản thân việc ánh xạ giữa use case và tính năng có thể tuân theo phân phối lũy thừa
  • Theo kinh nghiệm từng xử lý từ quy mô nhỏ (vài trăm sự kiện mỗi giờ) đến quy mô lớn (hàng nghìn tỷ sự kiện mỗi giờ), trước tiên cần xem có thực sự cần queue hay không

    1. Có thể chỉ polling DB đơn thuần là đủ
    2. Nếu một node có thể gánh được thì có thể xử lý bằng serverless hoặc một process đơn
    3. Nếu chưa đến mức bắt buộc cần distributed queue, thì load balancing + REST API + retry bất đồng bộ cũng đã đủ
    4. Nếu thực sự cần distributed queue thì tôi nghĩ dùng giải pháp chuyên dụng như Kafka sẽ tốt hơn
    • Cần nói rõ rằng Kafka thực ra không phải queue mà là hệ thống log phân tán. Nhiều người hay hiểu nhầm nó là vật thay thế MQ
    • Ở startup, kỹ sư đôi khi có xu hướng chọn công nghệ phức tạp với suy nghĩ về bước tiếp theo trong sự nghiệp hơn là dự án hiện tại
    • Nếu thiết kế cấu trúc code để hỗ trợ cả queue dựa trên PostgreSQL lẫn queue dựa trên Kafka, thì sau này sẽ dễ chuyển đổi hơn
    • PostgreSQL dễ trở thành nút thắt khi tải ghi tăng cao. Stream UPDATE đặc biệt đau đầu
    • Với tư cách là một lập trình viên Java, tôi luôn cần queue. Polling DB là cơn đau đầu trong môi trường nhiều consumer/producer. consumer group và partition của Kafka đã giúp ích rất nhiều cho việc quản lý trạng thái
  • Cách tiếp cận dùng Postgres cho mọi mục đích là nguy hiểm
    Lock và mức độ tuần tự hóa không trực quan, nên có thể tạo ra nút thắt hiệu năng
    Tôi đã dùng Postgres hàng chục năm, nhưng không nên thiết kế dựa trên niềm tin mù quáng

    • Khi lưu lượng tăng đột biến, giới hạn scale theo chiều dọc là vấn đề. Kafka hấp thụ được burst traffic còn Postgres thì dễ quá tải
    • Sẽ rất tốt nếu Postgres có thêm cấu trúc queue bền vững, nhưng rất khó scale vượt mức Redis và LISTEN/NOTIFY thì không scale được (liên kết liên quan)
    • Thực ra mọi kho dữ liệu đều đòi hỏi phải hiểu mô hình đồng thời. Ngay cả giữa các RDBMS cũng có khác biệt lớn
    • Postgres khó mở rộng vô hạn, nhưng với xử lý theo lô và thao tác ở cấp từng hàng, nó vẫn có thể xử lý khá nhiều dữ liệu
    • Cá nhân tôi thường bắt đầu với Postgres trước, rồi khi xuất hiện nút thắt mới chuyển sang hệ thống khác
  • Tôi nghĩ cách tiếp cận bằng bảng event log dựa trên SQL khá hiệu quả
    Tuy nhiên nhược điểm là thiếu công cụ ở phía client. Kafka có lợi thế ở điểm này vì hệ sinh thái thư viện rất phong phú
    Công ty chúng tôi đã chuẩn hóa việc truyền event giữa các service theo hướng SQL-based (feedapi-spec)
    Nó chưa trưởng thành như Kafka, nhưng có tiềm năng phát triển thành một stack thư viện chung hỗ trợ nhiều storage engine

    • Khi các công cụ sinh mã dựa trên LLM phát triển, việc lấp đầy khoảng trống phía client như thế này đã trở nên dễ hơn
    • Với người không thích Kafka như tôi thì cách tiếp cận này hấp dẫn hơn nhiều
  • Dạo này mọi người có xu hướng bị hấp dẫn quá mức bởi công nghệ mới
    Postgres rất tuyệt, nhưng phải dùng đúng công cụ cho đúng vấn đề
    Postgres không được thiết kế cho pub-sub, còn Kafka được tạo ra cho mục đích đó
    Nên tránh xu hướng mọi sản phẩm đều muốn “làm tất cả mọi thứ”. Tôi nghĩ những công cụ làm tốt một việc sẽ tốt hơn

  • Việc triển khai “số offset tăng đơn điệu” là một bài toán khó
    Sequence đơn giản gây ra vấn đề vì thứ tự transaction và thời điểm commit có thể lệch nhau

    • Một cách là dùng bảng chuyên cho counter và đảm bảo thứ tự bằng lock trong cùng transaction (liên kết tham khảo)
    • Cũng có thể dùng Lamport Clock hoặc Vector Clock để đảm bảo thứ tự trong môi trường phân tán (Lamport timestamp, Vector clock)
    • Thay vì ép một thứ tự tuyệt đối, sẽ thực tế hơn nếu gán số theo đơn vị batch, hoặc để một process riêng gán thứ tự sau khi commit
    • Cũng có cách dùng “SELECT FOR UPDATE SKIP LOCKED” để tránh xử lý trùng lặp
  • Tôi nghi ngờ liệu họ có thực sự benchmark Kafka hay chưa
    Kết quả đạt được trên môi trường 96 vCPU thì Kafka cũng có thể đạt với cấu hình 4 vCPU
    Hiệu năng Postgres đang chậm một cách bất thường
    Nếu không cần Kafka thì đừng dùng, nhưng khoe Postgres đạt 5k msg/s thì không có nhiều ý nghĩa

    • Redpanda (bản triển khai tương thích Kafka) xử lý được 250 nghìn message mỗi giây ngay trên laptop (liên kết video)
    • Hiệu năng còn thấp hơn thế trên môi trường 288 vCPU là một sự lãng phí
    • Nếu lý do dùng Postgres chỉ đơn giản là “vì đã có sẵn” thì tôi hiểu, nhưng vẫn cần kiểm chứng trước khi thêm hạ tầng mới
    • Kafka có thể chạm tới giới hạn băng thông mạng ngay cả với phần cứng ít hơn
    • Vận hành chỉ một instance 24xlarge trên AWS là không hiệu quả, và với chi phí đó có thể vận hành được một cụm Kafka lớn
  • Có hai thái cực: “những người ám ảnh với công nghệ mới” và “những người chỉ khư khư cái mình đã học”
    Một kỹ sư thực tế sẽ đưa ra lựa chọn thực dụng ở đâu đó giữa hai bên

    • Tôi thuộc kiểu thứ ba: kiểu người nghĩ rằng “mọi thứ hiện có đều dở, còn cái mới rồi cũng sẽ dở thôi”
    • Cuối cùng điều quan trọng là nhìn vấn đề một cách hợp lý và tìm ra giải pháp tối ưu
    • Ví dụ, có thể thử thay Elasticsearch bằng Postgres, nhưng độ hoàn thiện của tính năng tìm kiếm thì ES vượt trội hơn hẳn
  • Chức năng cốt lõi của Kafka là kiểm soát offset theo từng consumer
    Đây là tính năng thiết yếu trong môi trường có nhiều team cùng đọc một topic
    Việc có thể điều chỉnh offset tiến hoặc lùi đã nhiều lần trở thành phao cứu sinh
    Tôi tự hỏi queue trên Postgres có hỗ trợ kiểu tính năng này không

    • Cũng có ý kiến cho rằng mỗi consumer tự quản lý offset của mình là được
    • Nhưng trong đa số trường hợp, nếu không cần thông lượng cao thì cũng không cần đến mức quản lý offset phức tạp như Kafka
    • Rốt cuộc đây là bài toán cân bằng giữa tốc độ theo yêu cầu nghiệp vụđộ phức tạp vận hành
  • Chính cách phân chia thành “phe chạy theo buzzword vs phe thường thức” đã là sai rồi
    Việc cố tái hiện Kafka bằng Postgres không phải là thường thức
    Nếu thực sự cần mức tính năng như Kafka thì cứ dùng Kafka là được

    • Trên thực tế họ không triển khai toàn bộ Kafka, mà chỉ làm ra hai truy vấn pub-sub đơn giản thôi