Actionbase – Cơ sở dữ liệu cho tính năng thích, đã xem gần đây và theo dõi
(github.com/kakao)Chúng tôi đã công bố mã nguồn mở Actionbase, cơ sở dữ liệu dành cho các tính năng như thích, sản phẩm đã xem gần đây và theo dõi.
Xin chào, tôi là một nhà phát triển đang cùng xây dựng Actionbase tại Kakao.
Tối qua lúc 8 giờ (ngày 27), chúng tôi đã đăng Actionbase lên Hacker News (Show HN), và chỉ sau khoảng 1 giờ 30 phút kể từ khi đăng, nó đã vươn lên vị trí số 1 trên trang đầu. Thực ra mục tiêu của chúng tôi chỉ là trụ lại ở trang đầu, nhưng phản hồi nhận được còn tốt hơn mong đợi.
Tại sao chúng tôi tạo ra nó?
Những tính năng như thích, sản phẩm đã xem gần đây hay theo dõi có thể hơi khác nhau giữa các dịch vụ, nhưng cuối cùng vẫn lặp đi lặp lại cùng một kiểu cấu trúc dữ liệu và cách xử lý.
Vấn đề là mỗi đội lại triển khai danh sách xuôi/ngược, bộ đếm và chỉ mục theo cách hơi khác nhau. Cách xử lý retry hay thứ tự sự kiện cũng không đồng nhất, nên đôi khi dữ liệu bị lệch một cách tinh vi, và cách tạo dữ liệu tổng hợp như số lượt thích cũng khác nhau giữa các đội, khiến việc vận hành trở nên khó khăn.
Nó hoạt động như thế nào?
Actionbase định nghĩa điều này bằng mô hình quan hệ ai (actor) đã làm gì (action) với cái gì (target), và tính toán trước mọi thứ tại thời điểm ghi. Vì phía đọc chỉ còn là truy vấn đơn giản nên vừa nhanh vừa dễ dự đoán.
Áp dụng vào production
Ứng dụng production đầu tiên là KakaoTalk Quà tặng Wish. Khi đó vẫn còn nhiều thiếu sót, nhưng để đáp lại kỳ vọng đó, chúng tôi đã sửa rất nhiều thứ, và trải nghiệm ấy đã trở thành động lực giúp dự án phát triển.
Hiện nay, nó đang xử lý hơn 1 triệu yêu cầu mỗi phút trong nhiều năm qua cho nhiều dịch vụ của Kakao. Kho lưu trữ dựa trên HBase, và chúng tôi cũng đang chuẩn bị một kho lưu trữ nhẹ (dựa trên SlateDB) để có thể đáp ứng nhiều quy mô khác nhau.
Bắt đầu
Bạn có thể chạy thử ngay bằng Docker:
docker run -it ghcr.io/kakao/actionbase:standalone
- 📦 GitHub: https://github.com/kakao/actionbase
- 🚀 Bắt đầu nhanh: https://actionbase.io/quick-start/
Chúng tôi rất cảm kích mọi câu hỏi, phản hồi và ngôi sao.
Trân trọng, @em3s, @zipdoki, @eazyhozy
Hỏi & Đáp
H: Dùng Redis cũng được mà, đúng không?
Đúng vậy. Chúng tôi cũng dùng Redis làm cache cho dữ liệu nóng. Tuy nhiên, khi quy mô tăng lên, chúng tôi gặp phải vấn đề các đội triển khai trùng lặp và dữ liệu sai lệch do thứ tự sự kiện bị rối.
H: Chỉ cần sharding PostgreSQL/MySQL là được mà?
Nhiều đội làm như vậy. Những vấn đề chúng tôi gặp phải là hot entity, truy vấn cross-shard và chiến lược cache khác nhau giữa từng dịch vụ. Chúng tôi cần một mô hình có thể scale ngang mà không phải thiết kế lại chiến lược sharding mỗi lần.
H: Write-time precompute hoạt động như thế nào?
Tại thời điểm ghi: ghi WAL → khóa → chuyển trạng thái → tính toán count/index → lưu → phát hành CDC. Phía đọc thì chỉ cần một GET hoặc SCAN đơn lẻ.
H: Nếu thứ tự sự kiện bị rối thì sao?
Mỗi mutation đều được gắn version (thường là timestamp). Ngay cả khi sự kiện đến theo thứ tự like(t=100) → like(t=300) → unlike(t=200), trạng thái cuối cùng vẫn hội tụ chính xác dựa trên version. Mục tiêu là ngay cả khi replay cùng một sự kiện, nó vẫn hội tụ về cùng một trạng thái.
H: Hiệu năng thực tế thế nào?
Trong production của KakaoTalk Quà tặng, hệ thống đang xử lý liên tục hơn 1 triệu yêu cầu mỗi phút, với đỉnh khoảng 2 triệu. Độ trễ đọc là p50 khoảng 2~3ms, p99 khoảng 10ms. Điểm cốt lõi không phải là con số tuyệt đối mà là độ trễ có giới hạn. Vì phía đọc là tra cứu đã được tính toán sẵn chứ không phải tổng hợp tại chỗ, hiệu năng không suy giảm ngay cả khi dữ liệu tăng lên.
H: Phù hợp với những use case nào?
Thích/reaction, theo dõi/follower, và sản phẩm đã xem gần đây là các use case cốt lõi. Với feature cho recommendation/ML, có thể cung cấp dữ liệu huấn luyện thông qua CDC, nhưng không trực tiếp phục vụ recommendation. Tin nhắn chat có lẽ không phải là lựa chọn tốt nhất—vì nó cần các mẫu truy cập khác như phân trang, tìm kiếm và luồng thảo luận. Giỏ hàng thương mại điện tử cũng cần transaction, trong khi Actionbase không hỗ trợ transaction cross-edge.
H: Có phải overengineering không? / Chỉ công ty lớn mới cần đúng không?
Có thể là vậy. Thành thật mà nói, nếu quy mô nhỏ thì PostgreSQL + Redis được tinh chỉnh tốt mới là câu trả lời phù hợp. Những vấn đề mà Actionbase giải quyết—độ phức tạp của sharding, cache invalidation, và sự trùng lặp giữa các đội—chỉ xuất hiện khi quy mô đủ lớn hoặc khi nhiều đội cùng xây các tính năng tương tự. Chúng tôi tạo ra nó vì đã nhiều lần đụng phải bức tường đó. Vì vậy, chúng tôi cũng đang chuẩn bị backend nhẹ (SlateDB) để có thể dùng được trong các triển khai nhỏ hơn.
24 bình luận
Ồ... tôi cũng đang mong chờ cả phiên bản backend nhẹ nữa!!
Cảm ơn bạn! Tôi đã định hướng dùng backend gọn nhẹ dựa trên SlateDB chỉ cần có S3, nhưng vẫn chưa thể bắt đầu nghiêm túc.
Tiện thể, tôi cũng muốn hỏi là bạn đang dự định dùng trong môi trường nào. Dự án side project? Production quy mô nhỏ? Tôi muốn tham khảo để sắp xếp thứ tự ưu tiên.
Nếu có thời gian, mong bạn vote cho HBase/SlateDB nữa. Ý kiến từ cộng đồng có lẽ sẽ giúp ích cho việc định hướng: https://github.com/kakao/actionbase/discussions/144
Tôi nghĩ đây là một dự án cực kỳ thực dụng.
Thật tuyệt vời!
Cảm ơn bạn! Tôi đang bù đắp cho sự tiếc nuối vì không nhận được nhiều sự quan tâm trên Show HN ở đây.
Tôi khá tò mò không biết bạn thấy phần nào là thực tế, hữu ích. Bạn từng gặp vấn đề tương tự chưa? Hay bạn đang ở trong tình huống cần triển khai tính năng đó?
Và nhân có dịp để lại bình luận, có một điều tôi muốn nói thêm. Trong tài liệu, tôi có ghi là không làm unbounded traversal, nhưng bounded multi-hop nằm trong kế hoạch của năm nay. Kiểu truy vấn 2-hop như "sản phẩm mà bạn bè đã thích" ấy. https://actionbase.io/ko/stories/unified-graph/
Điều tôi cảm thấy thực tế là,
Bản thân tôi cũng từng có trải nghiệm với những trăn trở tương tự, và cũng đã từng triển khai một lớp trừu tượng hóa ở mức code dựa trên KV store như Redis, nên tôi thấy mục tiêu và định hướng mà tài liệu muốn truyền tải, cũng như cấu trúc tổng thể, đều rất thực tế.
Ngoài ra, tôi thấy rất hay khi họ đã tập hợp và phản ánh nhu cầu cũng như trăn trở của nhiều team để tạo ra một sản phẩm nội bộ của công ty, rồi công bố nó dưới dạng mã nguồn mở. haha
Cuối cùng, nếu phải nói thêm cho bằng được thì với những người sẽ sử dụng, tài liệu hiện tại có lẽ đã là đủ, nhưng tôi nghĩ sẽ còn hấp dẫn hơn nữa nếu có thêm ví dụ triển khai có thể làm theo gần như ở mức sao chép-dán, cùng với các cách dùng được khuyến nghị hoặc tài liệu tham chiếu về hạ tầng được lồng vào dưới dạng example.
Cố lên!
Thật lòng mà nói, tôi rất vui khi biết bạn cũng đã có cùng trăn trở như vậy. Và tôi cũng chân thành cảm ơn vì bạn đã nhận xét là nó rất tuyệt.
Tôi đồng cảm với điểm bạn nói. Tôi cũng muốn những phần dùng như công cụ thì được thiết lập thật thuận tiện để có thể tập trung vào bài toán mà mình cần giải quyết.
Tuy nhiên, hiện tại đây vẫn là giai đoạn đầu của mã nguồn mở, và trong quỹ thời gian hạn chế, chúng tôi tập trung vào việc làm sao truyền đạt được giá trị cốt lõi này. Nếu không truyền đạt được, thì ngay cả những người thực sự có thể giải quyết vấn đề cũng sẽ khó làm được. Giờ chúng tôi định tiến theo hướng bạn nói. Tuy vậy, chúng tôi muốn nhận thêm phản hồi xem nên đi với HBase + Kafka là stack nội bộ, hay dù tốn thêm công sức phát triển mới thì vẫn đi với SlateDB + S2. Bên tôi có các kỹ sư HBase vận hành nên đang dùng khá thoải mái, nhưng chắc hẳn nhiều nơi không được như vậy. Nếu bạn để lại ý kiến thì chúng tôi sẽ rất cảm kích (dù chỉ vote thôi cũng được):
https://github.com/kakao/actionbase/discussions/144
Tôi cũng thấy roadmap như truy vấn 2-hop mà bạn nhắc tới rất hấp dẫn.
Nhưng tôi nghĩ nếu diễn đạt thật tốt điều mà tài liệu hiện tại muốn truyền tải bằng các ví dụ như code thì sẽ nhận được phản ứng bùng nổ hơn nhiều.
Tôi đồng ý. "Ý là phải lồng ghép thật khéo vào ví dụ". Nhưng hóa ra chuyện này không hề dễ như vẻ ngoài của nó, huhu. Tôi sẽ suy nghĩ thêm theo nhiều hướng khác nhau. Cảm ơn bạn!
Không biết bạn đã xem hướng dẫn tương tác mà đồng nghiệp của chúng tôi đã chuẩn bị rất công phu chưa: https://actionbase.io/guides/build-your-social-media-app/. Đây cũng là một nỗ lực theo hướng đó. Tôi thấy mình cần nhìn lại xem nó có phù hợp với định hướng bạn nói hay không. Chúng tôi sẽ tiếp tục cố gắng.
À, còn một điểm tôi bị sót khi bình luận thêm là không chỉ phần hướng dẫn, mà nhìn chung có thể cảm nhận được nhiều công sức đã được đầu tư vào cách tổ chức tài liệu.
Tuy vậy, như tôi đã nói trước đó, sẽ còn tốt hơn nếu cấu hình được chuẩn bị sẵn cho ví dụ có thể được làm để người dùng dễ dàng làm theo thông qua
git clone.Tôi sẽ trả lời cùng trong bình luận bên dưới.
Tôi cứ tưởng mình đã viết bình luận này rồi, nhưng không thấy đâu nên phải viết lại từ đầu...(huhu)
Cảm ơn vì đã trả lời rất chân thành và kỹ lưỡng cho một bình luận tôi viết khá nhẹ nhàng.. haha;;
Dù sao thì điều tôi muốn nói là, tôi nghĩ môi trường của một đội nhỏ hoặc một đội lớn muốn thử áp dụng cái này sẽ rất khác nhau, và khi nghĩ đơn giản kiểu “hay là thử đưa cái này vào nhỉ?”, thì hình thức dễ thuyết phục nhất có lẽ là một dự án mẫu được viết bằng ngôn ngữ mà đội đang sử dụng.
Nếu trước hết tạo các dự án mẫu cho những ngôn ngữ phổ biến, rồi từ đó xây dựng phần bắt đầu nhanh, thì người ta sẽ dễ đọc hơn nhiều với tâm thế thoải mái, và tôi nghĩ việc chỉ cần
git clonerồi làm cái rụp để thử ngay chính là điểm hấp dẫn.Và tôi cũng nghĩ cách này là tốt nhất để giải thích các best practice.
Tất nhiên tôi hiểu rằng do đặc thù của dự án, làm vậy sẽ không hề đơn giản, nhưng dù vậy tôi vẫn nghĩ đó là cách hấp dẫn nhất.
Ngoài ra, nếu có thể xây dựng ví dụ cùng với các công cụ như pulumi hoặc terraform thì có lẽ sẽ còn tốt hơn nữa.
Đây là một góc nhìn mà tôi hoàn toàn chưa từng nghĩ tới. Thật sự cảm ơn vì đề xuất này. Đây đúng là một trải nghiệm rất tốt mà có thể nhận được từ cộng đồng.
Tôi sẽ suy nghĩ xem làm thế nào để hiện thực hóa hướng đi mà bạn đã nói. Cả các ví dụ về
pulumihayterraformnữa. Có lẽ chúng tôi cũng có thể sắp xếp lại định hướng rồi nhờ cộng đồng hỗ trợ. Nếu khi đó bạn có thể đóng góp thì chúng tôi sẽ càng biết ơn hơn.Ngoài ra, tôi cũng đang suy nghĩ xem trong thời đại vibe coding thì làm thế nào để trở thành nền tảng cơ sở cho điều đó. Khi nói "hãy tạo ứng dụng cho tôi", người ta sẽ viết bằng React, Svelte, v.v. Đó là vị thế tương tự. Ý tôi là tình huống khi nói "hãy thêm tính năng like" thì Actionbase sẽ đảm nhận vai trò đó.
Phần này cũng vẫn luôn quanh quẩn trong đầu tôi. Vì vậy tôi đã rất chú trọng đến việc tài liệu hóa để các công cụ AI có thể đọc được, và gần đây cũng đang nhìn thấy khả năng ở đó.
Tham khảo:
llms.txt - https://actionbase.io/llms-txt/
Thử nghiệm recipe của đội thắng hackathon Anthropic - https://github.com/kakao/actionbase/discussions/90
Có vẻ sẽ dùng rất tốt ở những nơi có use case tương tự. Cảm ơn bạn đã công khai!
Tuy nhiên, tôi hơi tò mò không biết ở phần ingestion, đoạn dùng Lock có gặp vấn đề gì không. Trong trường hợp ghi dữ liệu thì lưu lượng truy cập khi đó ở mức nào? Có khi nào phát sinh vấn đề do tranh chấp Lock hay không?
Cảm ơn bạn vì câu hỏi rất hay!
Lock được áp dụng ở cấp độ cặp edge (source, target) (ví dụ: Alice→Phone). Chỉ khi có ghi đồng thời vào cùng một edge thì mới phát sinh tranh chấp, nhưng trên thực tế rất hiếm khi một người dùng cùng lúc nhấn thích trên cùng một đối tượng, nên mức độ tranh chấp thấp. Đây là đặc trưng trong use case cơ sở dữ liệu của chúng tôi.
Lưu lượng ghi ở thời điểm đỉnh vào khoảng vài trăm nghìn lượt mỗi phút. Lượt đọc là hơn 1 triệu+, còn ghi thì thấp hơn mức đó. Tham khảo benchmark (đọc 85%, ghi 15%) - https://actionbase.io/ko/operations/benchmarks/
Với các thực thể nóng (như sản phẩm phổ biến), có thể xảy ra tranh chấp lock, và nguyên nhân là do cập nhật count (HBase Increment). Phần này chúng tôi đang tối ưu riêng để xử lý. Liên quan đến ghi tần suất cao: https://actionbase.io/ko/stories/kakaotalk-gift-recent-views/
Ồ.....
Cảm ơn bạn! Nếu quan tâm, hãy để lại ý kiến về hướng đi tiếp theo tại đây: https://github.com/kakao/actionbase/discussions/144
Wow, cái này có vẻ sẽ cực kỳ hữu ích.
Cảm ơn bạn! Không biết khi triển khai các tính năng tương tự, bạn đã gặp phải vấn đề nào chưa? Bọn mình đang thu thập ý kiến từ cộng đồng về việc nên ưu tiên làm gì tiếp theo: https://github.com/kakao/actionbase/discussions/144
Tài liệu cho nhà phát triển được viết rất tốt. Các trường hợp sử dụng được giới thiệu bằng stories, phần bắt đầu nhanh và FAQ đều rất đầy đặn, đến mức có cảm giác như một blog kỹ thuật.
Wow, thật sự cảm ơn bạn. Từ khi công bố mã nguồn mở vào ngày 5 tháng 1 đến khi mở cho cộng đồng vào ngày 27, chúng tôi đã đầu tư rất nhiều công sức vào tài liệu, nên rất vui vì được bạn ghi nhận.
Vì đây là giai đoạn đầu của mã nguồn mở nên chúng tôi tập trung vào việc "đây là gì, vì sao cần nó", và có lẽ nhờ vậy mà tài liệu mới ra được như thế này. Nếu trong lúc đọc tài liệu bạn thấy chỗ nào còn chưa ổn, cứ thoải mái góp ý nhé!
Tham khảo thêm, nếu tận dụng https://actionbase.io/llms-txt/ thì có thể bạn sẽ nhận được những kết quả ngoài mong đợi. Gần đây, khi thấy một người chưa hiểu rõ về Actionbase dùng prompt này để đi đến kết luận tối ưu cho những nhu cầu phức tạp, tôi lại một lần nữa cảm nhận rằng thế giới đúng là đã thay đổi rồi.
Hãy thử dùng nội dung sau trong ChatGPT, Claude, Gemini, v.v.
Đáng để nghi ngờ. Nhưng không phải tự dàn dựng đâu.
Tôi đã chèn 4 link vào bình luận đầu tiên nên bị shadowban trong 30 phút. Trong lúc đó phần giải thích ngữ cảnh không hiện ra nên mọi người cứ thế lướt qua. Lúc ấy tôi thật sự rất bất an. Sợ nó bị chìm mất. Sau khi bỏ link ra rồi đăng lại thì lúc đó mới lên hạng 1, và bình luận cũng bắt đầu xuất hiện.
Người bình luận mà bạn nói, tôi cũng đã kiểm tra rồi. Chuyện là tài khoản đó mới đăng ký chưa lâu. Dù vậy tôi vẫn thấy biết ơn. Dù sao thì cũng có phản hồi mà. Nên tôi đã trả lời rất cẩn thận. "why not redis?" Câu này tôi đã chuẩn bị trước rồi. Đây là kiểu câu hỏi cứ hễ liên quan đến DB là chắc chắn sẽ xuất hiện. Tôi đã nghĩ, chẳng lẽ mình chuẩn bị nghiêm túc thế này rồi mà lại vẫn có người hỏi đúng câu đó sao? Nhưng từ hôm trước, lúc đăng s2-streamstore, tôi đã biết rồi. Vì có người trả lời kiểu "sao không làm bằng TCP". Thế nên tôi đã chuẩn bị.
Tham khảo thêm, tôi đã dặn các thành viên trong nhóm tuyệt đối không được upvote hay để lại bình luận. Tôi còn bảo họ đăng xuất ra luôn để lỡ có sơ suất cũng không xảy ra. Vì tôi đã biết trước HN rất nhạy cảm với chuyện đó.
Dù sao thì, có giải thích thì có thể bạn vẫn không tin... nên xin hãy xem repo của bọn tôi một lần thôi. Đây là phần code đã sống sót. Tôi viết chi tiết thế này vì sợ những đồng nghiệp đã cùng làm việc sẽ tổn thương khi đọc bài này. https://github.com/kakao/actionbase/discussions/32 xin hãy xem một lần thôi. Cảm ơn bạn.
Và nữa,
https://actionbase.io/ko/stories/kakaotalk-gift-wish/ nữa. Nếu bạn từng suy nghĩ về hệ thống quy mô lớn thì có lẽ sẽ thấy hữu ích, nên tôi đã cố gắng viết thật chân thành.
À, và như bạn có thể thấy nếu xem bài đăng X của tôi bên dưới, hạng 1 là trước khi có bình luận đó. Bình luận ấy chắc được đăng khi nó đã tụt xuống hạng 2~3. Đúng lúc tôi lấy ra khỏi hộp ddujjonku ở khu vực ăn vặt thì bình luận xuất hiện, nên tôi chạy tới để bình luận. Sau đó trong 12 tiếng nó bị đẩy xuống tận hạng 30, còn bây giờ thì đang ở trang thứ 2 TT
Tôi cũng đã đăng lên X: https://x.com/enmskim/status/2016412136482996689
Actionbase – Cơ sở dữ liệu cho lượt thích, đã xem gần đây và theo dõi
x: https://x.com/enmskim/status/2016941043628097965