- Workflow bền vững (durable) lưu checkpoint trạng thái thực thi vào cơ sở dữ liệu, cho phép khôi phục từ bước hoàn tất cuối cùng sau sự cố
- Kiểu điều phối bên ngoài như Temporal, Airflow, AWS Step Functions làm tăng độ phức tạp vì bổ sung bộ điều phối trung tâm và kho lưu trữ
- Kiến trúc dựa trên Postgres cho phép máy chủ ứng dụng polling bảng workflow và lưu trực tiếp đầu ra của từng bước để có thể khôi phục
- Nhiều máy chủ có thể ngăn thực thi trùng lặp bằng khóa và ràng buộc toàn vẹn, đồng thời xử lý các vấn đề về mở rộng, tính sẵn sàng và khả năng quan sát bằng các giải pháp của Postgres
- Một Postgres đơn lẻ có thể mở rộng theo chiều dọc tới hàng chục nghìn workflow mỗi giây, đồng thời tận dụng nguyên bản replication, multi-AZ và phân tích bằng SQL
Mô hình cơ bản của workflow bền vững
- Workflow bền vững là cách định kỳ lưu checkpoint tiến độ thực thi chương trình vào cơ sở dữ liệu, để sau sự cố hoặc lỗi có thể khôi phục từ bước đã hoàn tất cuối cùng
- Có thể hình dung như cơ chế lưu và tải trong trò chơi điện tử: định kỳ “lưu” tiến trình chương trình và sau sự cố thì “tải” lại từ checkpoint gần nhất
- Cách triển khai phổ biến là các hệ thống điều phối bên ngoài như Temporal, Airflow, AWS Step Functions
- Trong mô hình điều phối bên ngoài, chương trình bền vững được viết thành một workflow gồm nhiều bước, và bộ điều phối trung tâm sẽ điều phối việc thực thi
Cách điều phối bên ngoài hoạt động
- Khi client gửi workflow, bộ điều phối tạo bản ghi trong kho dữ liệu rồi dispatch tới worker để thực thi
- Mỗi khi worker hoàn tất một bước, nó gửi kết quả về bộ điều phối; bộ điều phối checkpoint đầu ra đó vào kho dữ liệu rồi dispatch bước tiếp theo
- Nếu worker gặp sự cố hoặc lỗi, bộ điều phối sẽ dispatch lại workflow đó sang worker khác và cho bắt đầu từ bước checkpoint cuối cùng
- Cấu trúc này làm tăng độ phức tạp vì thêm máy chủ điều phối riêng vào ý tưởng cốt lõi là lưu trạng thái workflow trong cơ sở dữ liệu
Kiến trúc dùng Postgres làm bộ điều phối
- Nếu cốt lõi của workflow bền vững là checkpoint trạng thái chương trình vào cơ sở dữ liệu, thì dùng chính cơ sở dữ liệu làm bộ điều phối thay vì thêm một máy chủ điều phối riêng sẽ đơn giản và hiệu quả hơn
- Postgres là lựa chọn phù hợp để xây dựng workflow bền vững nhờ độ phổ biến, khả năng mở rộng và hệ sinh thái phong phú
- Trong hệ thống workflow bền vững dựa trên Postgres, các máy chủ ứng dụng giao tiếp trực tiếp với Postgres để chạy workflow thay vì đi qua bộ điều phối trung tâm
- Client gửi yêu cầu thực thi bằng cách tạo một mục trong bảng workflow của Postgres, còn máy chủ ứng dụng sẽ polling bảng đó để dequeue và thực thi workflow
- Trong quá trình chạy workflow, máy chủ checkpoint đầu ra của từng bước vào Postgres; nếu máy chủ đang chạy bị sự cố hoặc lỗi, máy chủ khác sẽ khôi phục workflow từ checkpoint
Vì sao không còn cần bộ điều phối trung tâm
- Các máy chủ ứng dụng có thể phối hợp thông qua Postgres, nên không cần bộ điều phối trung tâm dispatch workflow tới worker
- Các máy chủ có thể cùng dequeue workflow từ bảng Postgres, và dùng các cơ chế như mệnh đề khóa để bảo đảm mỗi workflow chỉ được đúng một worker dequeue
- Việc checkpoint đầu ra bước cũng do chính worker ghi trực tiếp vào Postgres thay vì thông qua bộ điều phối
- Nếu nhiều worker cố chạy cùng một workflow đồng thời, ràng buộc toàn vẹn của Postgres có thể phát hiện tác vụ trùng lặp tại thời điểm checkpoint và buộc chúng dừng lại
- Khi thay bộ điều phối trung tâm bằng Postgres hoặc cơ sở dữ liệu khác, các vấn đề như mở rộng, tính sẵn sàng, khả năng quan sát và bảo mật có thể được xử lý bằng những giải pháp Postgres native đã quen thuộc
Khả năng mở rộng và tính sẵn sàng
- Khả năng mở rộng và tính sẵn sàng của hệ thống workflow bền vững dựa trên cơ sở dữ liệu về cơ bản được quyết định bởi cơ sở dữ liệu nền tảng
- Có thể mở rộng theo chiều ngang bằng cách thêm máy chủ worker, nên thông lượng tối đa phụ thuộc vào việc cơ sở dữ liệu xử lý workflow nhanh đến mức nào
- Các worker có thể thay thế cho nhau và khôi phục trạng thái của nhau, nên hệ thống vẫn duy trì khả dụng miễn là cơ sở dữ liệu nền tảng còn hoạt động
- Khi dùng Postgres, ưu điểm là khả năng mở rộng và tính sẵn sàng đều là các bài toán đã được nghiên cứu lâu năm và có những lời giải vững chắc
- Một máy chủ Postgres đơn lẻ có thể mở rộng theo chiều dọc để xử lý hàng chục nghìn workflow mỗi giây
- Có thể mở rộng thêm bằng CockroachDB dạng Postgres phân tán hoặc Postgres được sharding
- Postgres hỗ trợ streaming replication kèm tự động failover, còn các dịch vụ managed thường cung cấp sẵn triển khai multi-AZ và SLA tính sẵn sàng cao
- Hàng chục năm kỹ thuật và nghiên cứu tích lũy để vận hành Postgres ở quy mô lớn cũng có thể được áp dụng trực tiếp cho việc vận hành workflow bền vững
Khả năng quan sát
- Trong mô hình thực thi bền vững dựa trên Postgres, workflow và các bước được checkpoint vào bảng Postgres, nên có thể quét các checkpoint đó để giám sát workflow theo thời gian thực và trực quan hóa quá trình thực thi
- Postgres có lợi thế ở chỗ gần như mọi truy vấn về khả năng quan sát workflow đều có thể biểu diễn bằng SQL
- Các tác vụ lọc và phân tích phức tạp, như truy vấn tìm tất cả workflow bị lỗi trong tháng qua, có thể được biểu diễn theo kiểu khai báo bằng SQL
- Điều này khả thi nhờ mô hình quan hệ của Postgres và hàng chục năm nghiên cứu tối ưu hóa truy vấn
- Nhiều hệ thống với mô hình dữ liệu đơn giản hơn, như kho key-value mà các bộ điều phối bên ngoài phổ biến sử dụng, không cung cấp cùng mức hỗ trợ phân tích dựa trên SQL
- Bằng cách lưu dữ liệu workflow và bước vào các bảng Postgres và thêm chỉ mục phụ cho các truy vấn phân tích nhanh, có thể đạt được khả năng quan sát hiệu quả cho thực thi bền vững
Độ tin cậy và bảo mật
- Trong mô hình thực thi bền vững dùng bộ điều phối bên ngoài, cả bộ điều phối và kho dữ liệu của nó đều trở thành điểm lỗi đơn
- Vì bộ điều phối và kho dữ liệu trực tiếp điều phối việc chạy workflow, chỉ cần một trong hai bị ngừng hoạt động là toàn bộ ứng dụng sẽ không thể sử dụng
- Chúng xử lý và lưu các checkpoint của workflow và từng bước, nên có thể truy cập dữ liệu ứng dụng nhạy cảm; do đó cần được hardening, kiểm soát truy cập và audit như hạ tầng nhạy cảm
- Trong mô hình thực thi bền vững dựa trên Postgres, điểm lỗi duy nhất là chính Postgres, và toàn bộ dữ liệu workflow được lưu trực tiếp vào Postgres mà không đi qua hệ thống nào khác
- Nếu ứng dụng vốn đã phụ thuộc vào Postgres, việc bổ sung thực thi bền vững sẽ không tạo thêm điểm lỗi mới và cũng không mở ra bề mặt tấn công mới cần bảo vệ
- Cơ sở dữ liệu vốn đã là hạ tầng cốt lõi, nên việc tái sử dụng cơ sở dữ liệu hiện có hợp lý hơn là bổ sung thêm một hạ tầng cốt lõi mới chỉ để điều phối
Tìm hiểu thêm
1 bình luận
Ý kiến trên Hacker News
absurdcủa Armin Ronacher là một triển khai workflow bền vững cho Postgreshttps://lucumr.pocoo.org/2025/11/3/absurd-workflows/
https://github.com/earendil-works/absurd
https://earendil-works.github.io/absurd/
Tôi chưa trực tiếp dùng thử, nhưng đây là một lựa chọn đáng để so sánh với các phương án khác
absurdvà bản triển khai phái sinh bằng Rust làdurablecó vẻ là lựa chọn tốt để giữ phía client cực kỳ đơn giảnNó nhẹ, nên coding agent có thể dễ dàng nắm toàn bộ cấu trúc trong đầu, và khi cần thì chỉ việc truy vấn trạng thái bằng query
Tôi đang dùng dbos.dev, restate.dev và cf workflows, và trong Agents.md của chúng tôi có ghi như sau
Restate.dev được dùng cho tích hợp thanh toán của northflank. Nó nhanh hơn cf workflows, độc lập với Cloudflare và các sự cố của Cloudflare, đồng thời có thể tự host nên không bị khóa vào nhà cung cấp
Cloudflare workflows được dùng cho các tác vụ ít quan trọng hơn như tạo báo cáo CSV/PDF, vì nó rất rẻ
DBOS.dev được dùng cho các workflow cần độ tin cậy/độ bền 100%, vì cần messaging nguyên tử gắn với giao dịch Postgres. Ví dụ như điền materialized row hoặc gửi email/push quan trọng cho merchant
DBOS và Restate nhìn bề ngoài khá giống nhau, nhưng Restate cần một “orchestrator” trung tâm nên có cả ưu và nhược điểm, đồng thời giúp việc xây dựng cùng các serverless worker của cf/vercel trở nên dễ hơn
Ngoài ra còn có VirtualObject, nên đây cũng là một phương án thay thế mã nguồn mở khá ổn, không bị khóa nhà cung cấp, cho DurableObject đơn luồng của Cloudflare
Có hai điểm mà DBOS đặc biệt tỏa sáng. 1) Với
dbos.enqueue_workflow, có thể thực hiện messaging nguyên tử trong cùng giao dịch DB với business logic. Đây thường là trường hợp mong manh nhất trong hầu hết các giải pháp, nên nếu xử lý được theo cách nguyên tử và bền vững trong cùng giao dịch đang chạy business logic thì độ phức tạp giảm đi rất nhiều2) DBOS lưu trạng thái workflow trong DB, nên có vẻ sẽ rất dễ tạo dashboard quan sát bằng metabase/looker. Sẽ rất hay nếu Restate cũng phơi bày instance rocksdb để có thể kết nối với metabase
Mình muốn biết trải nghiệm thực tế của những người đã dùng DBOS và Temporal
Trước đây tôi đã dùng Temporal và nó hoạt động khá tốt, nhưng từng có lúc thấy bất tiện khi xây dựng giải pháp vì giới hạn kích thước payload của request hoặc sự kiện
Việc nó ép buộc các thực hành kỹ thuật tốt cũng là một ưu điểm, nhưng tôi không phải lúc nào cũng muốn viết logic đặc biệt kiểu: vì file CSV lớn hơn 2MB nên phải tải lên S3, chuyển link, rồi trong workflow lại tải xuống
Tôi tò mò trải nghiệm với DBOS ra sao, và khi so với Temporal thì thế nào về độ phức tạp vận hành hay mức độ tương đương tính năng
Ở nhà tôi cũng chạy nó để xử lý các tác vụ tự động hóa gia đình không quá nhạy về thời gian. Độ trễ workflow không đến mức quá tệ, nhưng có lẽ tôi sẽ không dùng cho các trigger cần phản ứng ngay, như sự kiện phát hiện chuyển động trong nhà; còn với kiểu timeout để tắt thứ gì đó sau một thời gian không hoạt động thì ổn
Tôi khá thích cách đặt một REST API mỏng phía trước Temporal bên trong VPC hoặc cụm Kubernetes. Nhờ vậy các trigger dựa trên sự kiện không cần bận tâm đến xác thực Temporal hay kiểm tra trạng thái workflow, đồng thời giúp giữ cho sự kiện càng ít logic càng tốt
Ví dụ, trigger DB có thể tự chạy trực tiếp hoặc đẩy sự kiện vào hàng đợi, rồi handler gọi một REST API mỏng với các chi tiết sự kiện cần thiết. REST API có thể quyết định xem nên khởi động workflow, gửi signal tới workflow hiện có, hay bỏ qua. Mẫu này thay đổi tùy tình huống, nhưng trong trường hợp của tôi thì hay dùng
SignalWithStart, hoặc nếu không đáng để khởi động và cũng không có workflow hiện hữu thì cứ bỏNgoài ra, khi cần điều phối các hành vi độc lập với nhau trong vòng đời của một đối tượng đơn lẻ thì tính năng workflow cha/con rất hữu ích, và tôi cũng thích việc có thể hủy khi yếu tố bên ngoài làm thay đổi lộ trình tiến triển của đối tượng
Nói dài dòng một chút thì nó rất mạnh, dễ làm việc cùng, và giúp rất nhiều trong việc đưa logic vòng đời ra khỏi API. Nếu để trong API thì nợ kỹ thuật rất dễ tích tụ và việc quản lý sẽ trở nên bấp bênh. Tôi đồng ý rằng việc nó buộc phải theo các thực hành tốt sẽ tốt hơn là ném logic vào chỗ trông có vẻ tiện rồi sau này thành cạm bẫy khó thấy
Nhưng rồi tôi thử sản phẩm Cloud và sốc vì giá. Tôi đã tiêu hết 1.000 đô tín dụng miễn phí trước cả khi đưa lên production. Tôi cũng không muốn tự vận hành Temporal cục bộ
Cá nhân tôi nghĩ lựa chọn tốt nhất là chỉ lấy ý tưởng từ kiến trúc của nó rồi tự triển khai bằng Postgres
Tôi không thích nó 100%. Nó giống một phần gắn thêm hơn là thành phần cốt lõi, và vẫn còn là bản phát hành đầu tiên. Dù vậy, hiện tại có thể xem như vấn đề này về cơ bản đã được giải quyết
Với trải nghiệm vận hành production hơn 1 năm, tôi thấy Temporal có thiết kế không tốt, chậm, và cực kỳ nặng về mặt hạ tầng
Chỉ cần các tác vụ không quá nhỏ, ví dụ hơn 200 sự kiện cho mỗi workflow và chỉ vài trăm workflow chạy đồng thời suốt cả ngày, là bạn có thể tốn hàng triệu đô chi phí hạ tầng mà chất lượng vẫn không ổn
Khi chạy benchmark nội bộ thì các con số rất tệ
Đội sales cũng thực sự khủng khiếp và trông rất tuyệt vọng
Từ góc độ lập trình viên thì SDK khá tốt
Đừng bị kẹt vào nexus, và nếu đội sales gọi điện thì nhất định phải kéo bộ phận pháp lý vào cùng
Phải mất thời gian để hiểu cách migrate từ Celery, nhưng trong trường hợp của chúng tôi thì rất đáng
Conductor OSS cũng làm việc này khá tốt https://docs.conductor-oss.org/devguide/ai/index.html
https://github.com/agentspan-ai/agentspan về bản chất là một lớp SDK agent cho Conductor, có thể thêm tính bền vững và khả năng điều phối cho các agent langgraph, OpenAI, vercel, ADK mà không cần thay đổi mã
Sẽ rất tốt nếu thay vì tách riêng kho dữ liệu, máy trạng thái, các ràng buộc trạng thái hợp lệ, và logic chuyển giữa các trạng thái hợp lệ, ta có thể hợp nhất chúng thành một dạng hạt nhân của trạng thái ứng dụng
Thành thật mà nói, Postgres vốn đã có khá nhiều khả năng như vậy, nhưng ở cấp độ ứng dụng hay sản phẩm, tôi vẫn chưa thấy một bức tranh rõ ràng nào về việc cung cấp một tập trạng thái có thể chứng minh được mà ứng dụng có thể chuyển sang, rồi tự động phơi bày điều đó cho client theo cách hữu ích. Ví dụ như: người dùng này có thể thích bài viết này nhưng không thể chỉnh sửa nó
Trong mắt tôi nó trông giống một dạng colored Petri net, nhưng vẫn chưa thấy một mô hình trạng thái ứng dụng đơn giản tương tự như cách cơ sở dữ liệu có những ranh giới thành công được xác định rõ ràng
Tuy vậy tôi không chắc đó có phải là một sự tích hợp hoàn chỉnh hay không
Vì DBOS không hỗ trợ Rust, tôi đã triển khai một phiên bản Rust rất tối giản nhưng tương tự tại https://github.com/tensorzero/durable
Nó khá ổn định và có thể mở rộng, nhưng dĩ nhiên phải cực kỳ cẩn thận với triển khai SQL. Hy vọng điều này sẽ khiến độc giả ở đây thấy hứng thú
https://flawless.dev/
Tôi hoàn toàn hiểu và đồng ý với khái niệm này. Đây là một cách tuyệt vời để đưa kiểu tính bền vững này vào hệ thống workflow
Tuy vậy, với bộ não game thủ thì tôi muốn gọi nó là “save scumming quy mô lớn”. Nhiều người có lẽ đã biết cách tiếp cận này hoạt động hiệu quả, nhưng có thể chưa liên hệ nó với các khái niệm khoa học máy tính trừu tượng
Một chiến lược khác để tăng độ vững chắc là cấu thành workflow từ các phép toán idempotent. Điều này có thể hữu ích khi trạng thái workflow quá lớn nên khó sao lưu. Thay vào đó, nếu chạy lại công việc từ đầu, mọi thứ cho đến điểm có tiến triển trở lại đều sẽ trở thành no-op
Tôi vẫn luôn ngạc nhiên về số việc có thể làm chỉ với vài công cụ miễn là có Postgres trong hộp đồ nghề
Gần đây tôi đã phát triển một distributed queue, nó hoạt động rất tốt, benchmark cũng đẹp, và không có race condition hay xung đột nào. Tôi đã dùng
SKIP LOCKEDđể các worker có thể cạnh tranh một cách an toànĐể các worker trải trên nhiều node tránh va chạm, cũng có thể dùng mutex theo phạm vi session, tức
pg advisory lockSELECT FOR UPDATEthì khả năng mở rộng sẽ không tốtSửa: kiểm tra lại thì có vẻ giờ lời khuyên đã đổi theo hướng ngược lại
Rails có nhiều backend công việc dựa trên cơ sở dữ liệu, nhưng theo thông lệ thì job luôn chỉ làm một việc và nên kết thúc càng nhanh càng tốt nếu có thể
Vì vậy việc tạo workflow trở nên hơi gượng ép. Nó thành kiểu ở dòng cuối của job thứ nhất thì đưa job thứ hai vào queue, rồi ở dòng cuối của job thứ hai thì đưa job thứ ba vào queue
Backend job không hiển thị chúng như một workflow được liên kết mà xử lý như các job độc lập, và nếu muốn hiểu workflow ở mức cao thì phải đọc qua nhiều class job khác nhau
Gần đây Rails đã đưa vào khái niệm continuable, cho phép checkpoint theo từng bước và resume bên trong job, nhưng thông lệ giữ job theo trách nhiệm đơn lẻ vẫn rất mạnh, nên dùng cho workflow thực sự vẫn thấy khá gượng
Tôi tò mò không biết người khác có gặp tình huống này không và họ đã tìm ra cách giải quyết chưa
Đây là một pattern rất hay. Nên làm càng nhiều thứ càng tốt bên trong cơ sở dữ liệu
Spanner bên ngoài cung cấp change streams. Spanner nội bộ thì khác, chủ yếu vì trong một số trường hợp có yêu cầu mở rộng cực đoan, và cũng pha trộn cả lý do “nó đã chạy tốt rồi” lẫn lý do “change stream tùy ý thì đáng sợ”
Spanner nội bộ cho phép bất kỳ transaction nào cũng có thể ghi một queue entry. Ở đây queue về cơ bản là một bảng có nhận thức đặc biệt về thời gian. Có thể lên lịch giao nhận, các entry sẽ được đẩy từ queue tới handler, và handler cũng có thể thực hiện ghi DB bên trong transaction dequeue. Và vẫn giữ nguyên toàn bộ khả năng mở rộng đó