Vì sao cơ sở dữ liệu và sự phức tạp của chúng giờ đây không còn cần thiết
(blog.redplanetlabs.com)- Nguyên nhân của sự phức tạp ở backend không nằm ở khiếm khuyết của một sản phẩm cụ thể, mà ở chỗ cấu trúc khái niệm mà cơ sở dữ liệu đã duy trì từ lâu vẫn tiếp tục ràng buộc cách thiết kế ứng dụng
- Cơ sở dữ liệu hoạt động giống như trạng thái biến đổi toàn cục, và buộc lập trình viên phải gánh các mô hình dữ liệu cố định, schema hạn chế, cùng sự căng thẳng giữa chuẩn hóa và phi chuẩn hóa
- Phương án thay thế được đề xuất là kết hợp event sourcing và materialized views để tách dữ liệu gốc khỏi các view chỉ mục, đồng thời coi chỉ mục là các cấu trúc dữ liệu bền vững thay vì mô hình dữ liệu
- Rama của Red Planet Labs gom thu thập dữ liệu, xử lý, lập chỉ mục, truy vấn, triển khai và giám sát vào một nền tảng duy nhất thông qua depots, ETL, PStates và query topologies
- Trong ví dụ tái triển khai Mastodon ở quy mô Twitter, Rama được nói là chỉ cần 10k dòng code và 9 người-tháng, trong khi sản phẩm tiêu dùng tương đương của Twitter được so sánh là cần 1M dòng code và khoảng 200 người-năm
Điểm khởi đầu của sự phức tạp trong cơ sở dữ liệu
- Trọng tâm vấn đề không nằm ở API, khó khăn vận hành hay các giới hạn tùy tiện của một sản phẩm cơ sở dữ liệu cụ thể, mà ở cấu trúc khái niệm tập thể đã được duy trì cho đến ngày nay
- Chỉ khi một cách làm tốt hơn xuất hiện thì vấn đề của cách cũ mới hiện ra rõ hơn, và bài viết đưa ra sự kết hợp giữa event sourcing và materialized views như một phương án thay thế
Cơ sở dữ liệu như trạng thái biến đổi toàn cục
- Lập trình viên được dạy phải hạn chế tối đa việc dùng biến toàn cục, nhưng về bản chất cơ sở dữ liệu cũng là trạng thái biến đổi toàn cục
- Cơ sở dữ liệu có những điểm còn khó xử lý hơn biến toàn cục thông thường
- Tương tác trải rộng qua nhiều hệ thống nên khó suy luận trạng thái
- Trạng thái có tính bền vững nên ngay cả khi sửa bug, dữ liệu đã hỏng cũng không tự động được khôi phục
- Có những trường hợp khó xác định chính xác phạm vi hư hỏng hoặc khó sửa hoàn toàn
- Việc quay lại từ bản sao lưu hoặc ghép một phần bản sao lưu không phải là cách giải quyết tối ưu
- Nếu dùng event sourcing và materialized views thì có thể tính lại view từ log gốc, nhờ đó có cơ hội sửa trạng thái chỉ mục bị hỏng
Giới hạn của mô hình dữ liệu cố định
- Cơ sở dữ liệu được thiết kế xoay quanh các mô hình dữ liệu như key/value, document, relational, column-oriented, graph
- Vì một mô hình dữ liệu đơn lẻ khó hỗ trợ mọi use case, doanh nghiệp thường phải dùng nhiều cơ sở dữ liệu cùng lúc
- Một lớp trừu tượng chỉ mục tổng quát hơn không phải là mô hình dữ liệu mà là cấu trúc dữ liệu
- Key/value: map
- Document: map of maps
- Relational: map of maps, secondary indexes là các map bổ sung
- Column-oriented: map of sorted maps
- Các cấu trúc dữ liệu bền vững có thể được lưu trên đĩa nên có thể rất lớn, đồng thời cũng biểu diễn được các cấu trúc dữ liệu lồng nhau
- Nếu chỉ mục được mô tả bằng tổ hợp các cấu trúc dữ liệu, thì không chỉ tái tạo được các mô hình dữ liệu hiện có mà còn có thể tạo ra nhiều dạng chỉ mục đa dạng hơn
- Thay vì bẻ mô hình miền của ứng dụng cho khớp với cơ sở dữ liệu, nếu có thể làm cho hình thức lưu trữ phù hợp với mô hình miền thì độ phức tạp nền tảng sẽ giảm đi
Sự căng thẳng giữa chuẩn hóa và phi chuẩn hóa
- Người dùng cơ sở dữ liệu quan hệ rốt cuộc sẽ phải đối mặt với lựa chọn giữa chuẩn hóa và phi chuẩn hóa
- Lưu trữ đã chuẩn hóa tạo ra nguồn chân lý rõ ràng và giảm khả năng bất nhất, nhưng số lượng join tăng lên có thể làm chi phí truy vấn cao hơn
- Nếu vì hiệu năng mà lưu cùng một thông tin theo nhiều cách, bug có thể dẫn tới dữ liệu không nhất quán
- Kiến trúc RDBMS gộp nguồn chân lý và kho chỉ mục để truy vấn nhanh vào cùng một datastore
- Giải pháp là một cấu trúc tách riêng hai vai trò đó
- Một hệ thống con biểu diễn nguồn chân lý
- Hệ thống con khác materialize số lượng kho chỉ mục mong muốn từ nguồn đó
- Nếu hệ thống thứ hai có thể tính lại chỉ mục từ dữ liệu nguồn thì có thể sửa được các sai lệch
Schema hạn chế và biểu diễn miền
- Các loại giá trị có thể lưu trong cơ sở dữ liệu khác nhau rất nhiều tùy sản phẩm
- Có cơ sở dữ liệu chỉ cho phép blob như byte array
- Có cơ sở dữ liệu cho phép nhiều kiểu như số nguyên, số thực dấu chấm động, chuỗi, ngày tháng...
- Việc lưu dưới dạng biểu diễn hạng nhất để có thể trực tiếp truy vấn hoặc tổng hợp thông tin lồng nhau bên trong đối tượng miền là điều hiếm gặp
- Ngôn ngữ triển khai cơ sở dữ liệu và ngôn ngữ ứng dụng khác nhau nên khó tương tác, và các phần mở rộng như protobuf extension cho Postgres cũng rườm rà và bị hạn chế
- ORM ánh xạ giữa biểu diễn miền và biểu diễn cơ sở dữ liệu, nhưng sự trừu tượng này có thể bị rò rỉ và gây vấn đề
- Nếu phải lập chỉ mục dữ liệu theo cách khác với biểu diễn miền lý tưởng, sẽ cần code adapter và các truy vấn có thể thực hiện hiệu quả cũng có thể bị hạn chế
Triển khai phức tạp và mô hình à la carte
- Một backend hoàn chỉnh không chỉ gồm cơ sở dữ liệu, mà còn cần nhiều công cụ như hệ thống xử lý, công cụ giám sát, scheduler...
- Backend quy mô lớn có thể phải kết hợp hàng chục công cụ, và việc cập nhật ứng dụng trở thành quá trình điều phối migration, cập nhật code và thay đổi hạ tầng
- Để sẵn sàng cho production cần có telemetry đầy đủ, nhưng mỗi công cụ lại có cách thu thập khác nhau nên gom tất cả vào một dashboard giám sát cũng trở thành một bài toán kỹ thuật riêng
- Cách phát triển đang thống trị hiện nay gần với mô hình à la carte, tức chọn công cụ tối ưu cho từng phần kiến trúc rồi ghép lại
- Bản thân việc làm cho các công cụ được thiết kế độc lập hoạt động cùng nhau đã là một công việc lớn, và vì mô hình dữ liệu cố định cùng schema hạn chế nên thường phải uốn ứng dụng theo công cụ thay vì uốn công cụ theo ứng dụng
- Vì chưa có một mô hình gắn kết cho việc xây dựng backend nên mô hình à la carte mới trở nên phổ biến; còn với mô hình gắn kết, khả năng trừu tượng hóa, tự động hóa và tái sử dụng sẽ lớn hơn nhiều
Mô hình đơn giản để nhìn backend
- Hai chức năng chính của backend là nhận dữ liệu mới và trả lời câu hỏi về dữ liệu đó
- Truy vấn tổng quát nhất có thể được biểu diễn như việc chạy một hàm trên toàn bộ dữ liệu mà backend đã nhận
query = function(all data)
- Trong thực tế, tập dữ liệu có thể là 10PB và thời gian phản hồi truy vấn phải ở mức mili giây, nên hệ thống thực dụng cần có chỉ mục
- Mô hình có thêm chỉ mục được biểu diễn như sau
indexes = function(data)query = function(indexes)
- Backend hiện nay triển khai các thành phần của mô hình này bằng nhiều công cụ hẹp, tách rời nhau
- Backend RDBMS dùng chính RDBMS cho dữ liệu và chỉ mục, đồng thời có thể thêm cơ sở dữ liệu riêng như ElasticSearch cho việc lập chỉ mục bổ sung
- Tính toán thường được thực hiện trong handler của API server hoặc các job nền dựa trên queue và worker
- Backend quy mô lớn có thể kết hợp các công cụ như Cassandra, MongoDB, Neo4j, Kafka, Hadoop, Storm, Kafka Streams
- Từ đó đi đến kết luận rằng nếu có một công cụ triển khai tất cả các thành phần này theo cách tích hợp và đa dụng thì có thể tránh được những lớp phức tạp nói trên
Cấu thành của Rama và ví dụ Mastodon
- Rama là một nền tảng phát triển backend được thiết kế dựa trên các nguyên tắc đó
- Red Planet Labs đã công bố Rama vào ngày 15 tháng 8 với tagline “the 100x development platform”
- Là ví dụ về giảm chi phí, công ty đưa ra dự án tái triển khai Mastodon ở quy mô Twitter
- 100M bot đăng 3.500 bài mỗi giây
- Fanout trung bình là 403
- Sản phẩm tiêu dùng tương đương của Twitter được so sánh là cần 1M dòng code và khoảng 200 người-năm
- Bản triển khai bằng Rama cần 10k dòng code và 9 người-tháng
- Bản triển khai được công bố dưới dạng mã nguồn mở và được giới thiệu là complete, high-performance, production-ready
- Twitter được nói là đã tự xây các cơ sở dữ liệu chuyên biệt như social graph database, in-memory timeline database để đạt quy mô đó, đồng thời có hệ thống triển khai phức tạp với riêng cấu hình Puppet đã hơn 1M dòng
- Bản triển khai dựa trên Rama được mô tả là giải quyết các bài toán hiệu năng và mở rộng tương tự bằng cách kết hợp các thành phần nguyên thủy của Rama, thay vì tự tạo hạ tầng chuyên biệt mới cho từng bài toán con
- Các chỉ số hiệu năng của bản Mastodon được giới thiệu là ngang bằng hoặc tốt hơn số liệu của Twitter
Mô hình lập trình của Rama
- Các khái niệm của Rama tương ứng trực tiếp với mô hình backend đã nêu ở trên
- Depots: log phân tán chứa dữ liệu tùy ý, tương ứng với
data - PStates: viết tắt của partitioned state, tương ứng với chỉ mục
- ETLs: tương ứng với
function(data) - Queries: tương ứng với
function(indexes)
- Depots: log phân tán chứa dữ liệu tùy ý, tương ứng với
- Có thể tạo bao nhiêu PStates tùy ý dưới dạng tổ hợp bất kỳ của các cấu trúc dữ liệu bền vững
- ETL và query được biểu diễn bằng API dataflow Turing-complete, và việc tính toán có thể chạy phân tán
- Rama cung cấp tài liệu hướng dẫn cho Java API, đồng thời cũng có Clojure API
Cách Rama giảm độ phức tạp của cơ sở dữ liệu
- PStates của Rama đóng vai trò gần giống cơ sở dữ liệu, nhưng chỉ có thể được ghi từ ETL topology sở hữu PState đó
- Vì mọi thao tác ghi đều nằm trong cùng một ETL code nên việc suy luận trạng thái trở nên dễ hơn
- PStates hoạt động như materialized view nằm trên log event sourcing
- Vì depot data là nguồn chân lý nên PState có thể được tính lại
- Ràng buộc mô hình dữ liệu được xử lý bằng cách mô tả PStates dưới dạng cấu trúc dữ liệu
- Bản triển khai Mastodon dùng tới 33 PStates chỉ riêng cho profiles, statuses và timelines
- Có PState phục vụ 10 use case, cũng có PState chỉ phục vụ một use case duy nhất
- PStates có các thuộc tính durable, partitioned, incrementally replicated
- Incremental replication có nghĩa là khi leader partition gặp sự cố sẽ có partition khác sẵn sàng takeover
- Những gì nhìn thấy trên leader hiện tại được đảm bảo vẫn nhìn thấy trên leader sau đó
- Bài toán chuẩn hóa và phi chuẩn hóa được xử lý bằng cách tách depots và PStates một cách tường minh
- Vấn đề schema hạn chế được giảm nhẹ bằng cách dùng trực tiếp biểu diễn miền
- Các cấu trúc dữ liệu phổ thông như hash map, list
- Protocol Buffers
- Định nghĩa đối tượng lồng nhau
- Với các kiểu mà Rama không biết, có thể xử lý bằng cách đăng ký custom serializer
Triển khai, tích hợp, giám sát
- Ứng dụng Rama được gọi là modules, và mỗi module có thể gồm nhiều depots, ETLs, PStates và query topologies
- Rama cung cấp cơ chế tích hợp sẵn để triển khai, cập nhật và mở rộng module; mỗi thao tác được nói là có thể thực hiện bằng one-liner trên terminal
- Rama không phải công cụ “all or nothing”, mà được thiết kế để dễ tích hợp với các hệ thống khác, nên có thể được đưa dần vào kiến trúc hiện có
- Vì là nền tảng tích hợp nên Rama cũng tự đảm nhiệm giám sát
- Thu thập dữ liệu giám sát
- Xử lý
- Lập chỉ mục
- Trực quan hóa
- Cluster UI telemetry được dùng để hiểu hiệu năng của module, phát hiện và chẩn đoán vấn đề, cũng như quyết định thời điểm cần mở rộng
Lộ trình học và triển khai
- Các tài nguyên được gợi ý để tìm hiểu thêm về Rama gồm
- Nếu muốn dùng Rama trong production để xây tính năng mới, mở rộng hệ thống hiện có hoặc đơn giản hóa hạ tầng, có thể đăng ký private beta
- Với người dùng private beta, công ty nói rằng họ không chỉ hỗ trợ học Rama mà còn đồng hành trong việc viết code, tối ưu và kiểm thử
1 bình luận
Ý kiến trên Hacker News
“Như sẽ giải thích sau, cách tiếp cận tốt hơn là event sourcing và materialized view” — vậy rốt cuộc giải pháp là tăng độ phức tạp à. Tất nhiên là vậy rồi
Ví dụ trực tiếp là bản triển khai Mastodon ở quy mô Twitter mà chúng tôi đã xây dựng. Để tạo cùng tính năng ở quy mô lớn, lượng mã ít hơn đúng nghĩa 100 lần so với số mã Twitter phải viết, và cũng ít hơn hơn 40% so với bản triển khai chính thức của Mastodon. Không phải vì đây là lần thứ hai dùng cùng công cụ nên thiết kế tốt hơn, mà vì nó được xây dựng trên một abstraction về cơ bản tốt hơn
Tuy vậy, khi vượt qua một quy mô nhất định, mọi thứ đều trở thành vấn đề data engineering, và trong bối cảnh toàn hệ thống, cách này đôi khi lại là giải pháp tương đối đơn giản. Lời khuyên “cứ dùng mySQL/SQLite/Postgres đi” chỉ tuyệt vời cho đến trước thời điểm nó không còn hiệu lực
Tôi thật sự tin rằng nếu bài viết gốc của Martin Fowler về event sourcing chưa từng được viết thì mọi người đã tốt hơn. Trong 99% trường hợp, tôi xem đó là một ý tưởng tệ
Không biết tôi có bỏ lỡ gì không, nhưng bài viết dường như hoàn toàn bỏ qua các khái niệm như concurrency, isolation, constraints. Và cái gọi là “query topology” có vẻ cũng không mang tính khai báo, lại đẩy trách nhiệm lập kế hoạch/tối ưu hóa truy vấn sang người viết; thật sự coi đây là trải nghiệm lập trình viên tốt hơn sao?
Và đúng vậy, cách truy vấn của Rama là một cách tiếp cận vượt trội hơn nhiều. Lý do cần một bộ lập kế hoạch truy vấn phức tạp thường đến từ giới hạn của cách lập chỉ mục dữ liệu, đặc biệt là sự căng thẳng giữa chuẩn hóa và phi chuẩn hóa. Trong Rama, rất dễ cụ thể hóa một cách chắc chắn nhiều view đã được chuẩn bị sẵn theo đúng hình dạng mà truy vấn cần
Tutorial giới thiệu nhẹ nhàng các khái niệm của Rama ở đây: https://redplanetlabs.com/docs/~/tutorial1.html
Về câu “không một mô hình dữ liệu đơn lẻ nào có thể hỗ trợ mọi ca sử dụng”, về mặt lý thuyết không có miền hay tập miền hữu hạn nào không thể được mô hình hóa chính xác bằng các tuple và quan hệ của sự vật
Trong thực tế, phạm vi của một cơ sở dữ liệu/schema cụ thể thường bị giới hạn trong một doanh nghiệp hoặc một lĩnh vực vấn đề, nhưng miễn là các kiểu không chồng lấn không phù hợp thì điều này cũng không phải vấn đề lớn. Chỉ cần cẩn thận với tên gọi, đưa một nhà bán lẻ web và một công ty bảo hiểm vào cùng một schema vẫn có thể hoạt động đủ tốt
Đưa chính xác mọi thứ vào một cơ sở dữ liệu là siêu năng lực. Lý do lớn nhất khiến tôi nhấn mạnh điều này là để tránh các giao dịch phân tán trên nhiều kho dữ liệu. Nếu toàn bộ hoạt động kinh doanh diễn ra trong một hệ thống giao dịch duy nhất, ngữ nghĩa sẽ đơn giản đi một cách đáng kể
Khi mọi người thực sự bắt đầu dùng dữ liệu, một máy chủ DB cỡ lớn trị giá 1 triệu USD rẻ hơn nhiều so với một mảng dự phòng gồm các cơ sở dữ liệu giá rẻ. Dù là lập trình viên, nhà phân tích hay ban lãnh đạo, tất cả đều tiết kiệm được thời gian, có lẽ chỉ một số DBA là ngoại lệ
Ngay cả nếu về lý thuyết chỉ cần như vậy, một vấn đề dai dẳng khác là phần triển khai. Ngày nay phần lớn lập trình viên không hiểu rõ cơ sở dữ liệu hoạt động ra sao và nên dùng thế nào, nên sử dụng chúng rất tệ. Vì thế họ tạo ra các cơ sở dữ liệu mới như NoSQL để né tránh thực tế này, muốn phải suy nghĩ ít hơn và chỉ viết thêm mã kết dính. Điều đó cũng hóa ra có kết quả tệ hại
Không lâu nữa xu hướng sẽ lại đảo chiều, “chỉ một cơ sở dữ liệu lớn” sẽ lại lỗi thời, và một mô hình “đơn giản” khác sẽ xuất hiện. Giống như thời microservices, “nhiều cơ sở dữ liệu nhỏ” có thể được xem là đơn giản thay vì “một cơ sở dữ liệu lớn”. Nếu không hiểu lịch sử, ta buộc phải lặp lại nó
Điều này cũng giống như trong lập trình nói chung: không có một cấu trúc dữ liệu hay tổ hợp cấu trúc dữ liệu nào có thể hỗ trợ mọi ca sử dụng. Đôi khi cần map, đôi khi cần list, set, tổ hợp, hoặc một thứ hoàn toàn khác
Dĩ nhiên cấu trúc dữ liệu rất đa dạng, cũng cần hiệu năng, và nó quan trọng đến mức trở thành nút thắt mà người bình thường không thể đụng vào, mọi thay đổi đều phải cực kỳ an toàn. Còn có bảo mật nữa. Nếu ai đó tìm được cách đi từ phần lỗi phát triển sang phần HR hoặc tài chính chỉ dành cho lãnh đạo thì sao? Ai từng triển khai một hệ thống ERM đa năng sẽ biết hệ thống tích hợp khó khăn và đau đớn đến mức nào
Tuy nhiên đây là trường hợp cực đoan. Tôi tò mò người ta đã đi xa đến đâu và làm thế nào khi theo đuổi lý tưởng này. Tôi chưa từng thấy doanh nghiệp nào vận hành bằng một hệ thống duy nhất. Còn hệ thống quản lý tri thức cá nhân thì sao? Mọi thứ có khớp không? Chẳng phải ta vẫn dùng bảng tính cho các tác vụ nhanh, và tệp văn bản cho dạng tự do đó sao?
Trông như một bộ sưu tập buzzword. Tôi đã làm việc với cơ sở dữ liệu nhiều năm ở một trong những công ty lớn nhất thế giới, nhưng chưa từng nghe từ topology
Dù có tiết kiệm được chút thời gian nhờ thứ này, thời gian đó cũng sẽ bay vào việc học Java và framework này. Bản thân cơ sở dữ liệu không có vấn đề gì
Tôi đã định tạo bảng văn bản ở đây, nhưng cách hiển thị trang bị hỏng hoàn toàn nên đăng bằng ảnh chụp màn hình: https://imgur.com/a/XtwSkyx
Nếu giải thích Rama như cho một đứa trẻ năm tuổi thì nó là gì? Tài liệu cũng làm tôi bối rối: https://redplanetlabs.com/docs/~/index.html
Mong bỏ qua các buzzword như “chuyển đổi mô hình” hay “nền tảng”. Nếu cần sơ đồ thì tôi muốn đọc một bài giải thích rõ hơn
Rama chạy dưới dạng cluster, và nhiều ứng dụng được triển khai lên cluster đó dưới dạng “module”. Hệ thống cũng tích hợp sẵn telemetry sâu và chi tiết
Mô hình lập trình của Rama là event sourcing và materialized view. Khi tạo ứng dụng Rama, bạn materialize nhiều chỉ mục theo dạng mình muốn, với các tổ hợp cấu trúc dữ liệu bền vững khác nhau, nhiều đến mức cần thiết. Chỉ mục được materialize bằng API luồng dữ liệu phân tán
Rama khác quá nhiều so với những thứ đã có nên đó là phần giải thích cấp cao nhất mà tôi có thể đưa ra. Tài liệu tốt nhất để học nền tảng là rama-demo-gallery, trong đó có các ví dụ ngắn, chạy được đến cuối, kèm chú thích chi tiết về việc áp dụng Rama cho nhiều trường hợp sử dụng. Tất cả đều có khả năng mở rộng và chịu lỗi: https://github.com/redplanetlabs/rama-demo-gallery
Có một log sự kiện chỉ-append gọi là “Depot”; trên đó tạo các view tùy ý, gọi là “P-States”. Phần mềm Rama hứa hẹn cập nhật các view này với độ trễ thấp. Ứng dụng xây trên đó sẽ truy vấn view và gửi sự kiện/lệnh mới vào Depot
Tôi từng làm một dự án kéo dài một năm để xây dựng một engine materialized view linh hoạt trên một tập dữ liệu sự kiện live cỡ 1–10TB, và trước khi chuyển sang dự án khác, kiến trúc của chúng tôi cũng dần hội tụ về ý tưởng đưa code đến nơi có chỉ mục
Rama khá hấp dẫn với tôi, nhưng có lẽ tôi sẽ không dùng vì một lý do hoàn toàn phi lý: JVM. Tôi đơn giản là ghét Java/JVM. Giá mà kiến trúc này được port sang môi trường khác
Ở chỗ làm, chúng tôi tách read model và write model. Write model, tức nguồn sự thật, là một domain model quan hệ truyền thống có cả bất biến/ràng buộc, và tôi nghĩ đa số developer quen ORM sẽ không khó suy luận về nó
Hầu như mọi command cũng tạo event và publish vào hàng đợi domain event dùng chung. Read model do các worker tiêu thụ event tự tạo view theo cách mình cần, và cũng có thể tạo lại. Ví dụ dịch vụ quản lý người dùng là nguồn sự thật, còn các dịch vụ khác là view service để hiển thị UI phức tạp, tự tạo read model/chỉ mục riêng dựa trên event từ dịch vụ người dùng và các dịch vụ khác. Nếu không có cách này thì sẽ cần những phép join khổng lồ hoặc các lệnh gọi API liên dịch vụ chậm
Về mặt kỹ thuật có thể replay event. Thực tế chúng tôi từng replay toàn bộ event của 3 năm qua vì một lỗi trong platform code. Nhưng tôi nghĩ hầu như chưa bao giờ thật sự cần đến. Đôi khi phải tạo lại view vì bug, nhưng thường xử lý bằng các chương trình tạm thời kiểu script đặc thù hoặc SQL migration. Tôi không biết chính xác nên gọi kiến trúc của chúng tôi là gì, và cũng chưa từng nghe ai gọi nó là “event sourcing”
Rốt cuộc chỉ là MySQL + RabbitMQ cũ kỹ và một ít glue code. Tuy nhiên để làm cho đúng thì cũng không hề tầm thường vì transaction outbox, bảo đảm giao ít nhất một lần, eventual consistency, duy trì đúng thứ tự xử lý event, batch dữ liệu event, quản trị DB, xử lý khi event handler chết, v.v. Trong bối cảnh đây đã là một cấu hình độc lập ngôn ngữ, đã được kiểm chứng thực chiến, với cả producer/consumer PHP và Go, tôi tò mò không biết nếu không dùng Rama thì chúng tôi đang bỏ lỡ điều gì, và Rama giải quyết các vấn đề trong danh sách trên như thế nào. Rama có vẻ được định hướng nhiều hơn về phía Java
Chỉ mục của Rama linh hoạt hơn nhiều. Ví dụ nếu cần một tập lồng nhau có 100 triệu phần tử thì cũng rất đơn giản. Chỉ mục đồ thị xã hội kiểu ID người dùng → tập ID người theo dõi là ví dụ phổ biến. Chỉ mục chuỗi thời gian chia theo độ phân giải, tức thực thể → độ phân giải → bucket thời gian → thống kê, cũng đơn giản tương tự
Không có giới hạn về kiểu dữ liệu lưu trong Rama. Truy vấn Rama rất mạnh, và việc thực hiện truy vấn phân tán real-time theo yêu cầu trên một phần hoặc toàn bộ chỉ mục là dễ dàng. Telemetry sâu và chi tiết trên toàn ứng dụng cũng được tích hợp sẵn, nên không cần tự xây hay quản lý riêng
Triển khai cũng được tích hợp sẵn. Với cách hiện tại, cập nhật ứng dụng có thể trải qua nhiều hệ thống như code worker, schema migration, và đặc biệt nếu muốn không downtime thì trở thành một bài toán engineering khá khó. Rama tích hợp tính toán và lưu trữ từ đầu đến cuối, nên phát hành, cập nhật và mở rộng ứng dụng đều có thể làm bằng một dòng terminal
Rama mở rộng tốt hơn nhiều. Đây là Rama nhìn từ góc độ tính năng; còn việc khi code với Rama không có impedance mismatch tạo ra khác biệt lớn đến đâu thì khó diễn tả bằng lời, phải dùng thử mới biết. Rama dành cho JVM nên có thể dùng với bất kỳ ngôn ngữ JVM nào, và hiện cung cấp API Java và Clojure
Event được lưu ở đâu và theo định dạng nào? Tôi muốn nghe chi tiết hơn
Có vẻ thứ đang thiếu hiện giờ là một cái tên thật kêu để gắn cho toàn bộ hệ sinh thái này
Việc cụ thể hóa dữ liệu tại thời điểm thay đổi có thể có lợi khi sản phẩm cần làm một việc thật nhanh. Nhưng sẽ trở nên rắc rối ngay khi xuất hiện các giao dịch phức tạp phải được cập nhật cùng nhau bằng ghi nguyên tử, hoặc khi muốn thêm một tính năng mới cần sắp xếp dữ liệu theo cách khác
Tôi cũng rất không hài lòng với việc phần xây dựng ứng dụng lướt qua nhẹ nhàng kiểu “chỉ cần gắn thêm một chỉ mục là được”. Chỉ mục là trạng thái toàn cục, chỉ là được chuyển xuống một tầng bên dưới mà thôi
Đọc tài liệu này vẫn không rõ độc giả mục tiêu là ai và nó đang cố giải quyết vấn đề gì: https://redplanetlabs.com/docs/~/why-use-rama.html#gsc.tab=0
Có lẽ sẽ hữu ích nếu đưa ra một trường hợp thực tế rồi chuyển đổi để cho thấy làm bằng RAMA thì dễ và hiệu quả đến mức nào
Ví dụ đầu tiên là triển khai Mastodon ở quy mô Twitter, với lượng mã ít hơn 100 lần so với mã mà Twitter đã viết để xây dựng cùng một thứ ở quy mô lớn. Con số này chỉ tính riêng sản phẩm tiêu dùng. Nó cũng ít mã hơn hơn 40% so với triển khai chính thức của Mastodon vốn không có khả năng mở rộng: https://github.com/redplanetlabs/twitter-scale-mastodon
Kho rama-demo-gallery cũng có nhiều ví dụ ngắn, độc lập và được chú thích chi tiết về việc áp dụng Rama cho các trường hợp sử dụng rất khác nhau. Bao gồm quản lý hồ sơ người dùng, phân tích chuỗi thời gian, chuyển khoản ngân hàng mang tính nguyên tử và chịu lỗi: https://github.com/redplanetlabs/rama-demo-gallery
Nếu không thực sự vận hành một website có 40 triệu người dùng hằng ngày, thì có vẻ không thể tuyên bố rằng “client Mastodon ở quy mô Twitter” đã chứng minh được điều này. Không thể mô phỏng môi trường thực tế, các thay đổi mã và hạ tầng đi kèm, người dùng thật, lưu lượng mạng, v.v.