#191 - So sánh các mẫu Distributed Transaction trong microservices
Grokking Newsletter là newsletter hàng tuần của Grokking cho các bạn software engineers người Việt.
Trong số này chúng ta cùng tìm hiểu về: So sánh các distributed transaction khác nhau trong microservices, tìm hiểu về neural network và mô hình huấn luyện hoạt động như thế nào, nghe tác giả Erik Meijer giới thiệu về Reactive programming và cuối cùng là kỹ thuật lock trong Etcd.
Những bài viết hay
Distributed transaction patterns for microservices compared
Một vấn đề đa số hệ thống gặp phải là làm sao điều phối hành động ghi vào nhiều hơn 1 hệ thống dữ liệu. Để trả lời cho câu hỏi này thường cần các lời giải thích dài bao gồm các khái niệm về dual writes (ghi kép) và distributed transaction (giao dịch phân tán). Hiện có rất nhiều tài liệu chi tiết về các cách tiếp cận, pattern khác nhau để giải quyết vấn đề trên. Bài viết này tổng hợp lại những patterns về giao dịch phân tán, liệt kê ưu điểm, nhược điểm, ví dụ trong thực tế, và cuối cùng so sánh tất cả chúng với nhau. Các patterns chính trong bài bao gồm:
Modular Monolith: là kiến trúc monolith với mỗi module tuân theo các nguyên tắc của microservice. Mỗi module vẫn đóng gói (encapsulate) tất cả access vào data của nó, nhưng các hoạt động giao tiếp được sử dụng dưới dạng method call trong bộ nhớ. Các service được chuyển thành các library module để có thể được triển khai (deploy) trong một môi trường runtime chung. Các service phải được cùng sử dụng 1 database instance, nhờ vậy có thể tham gia trong cùng 1 local transaction, commit hoặc rollback cùng lúc.
Two-phase Commit (2PC): Để implement 2PC thì hệ thống cần 1 distributed transaction manager (đơn vị quản lý giao dịch phân tán), một lớp lưu trữ transaction log, và các datasource có tính DPT XA-compatiple với các XA driver tương ứng, ví dụ như các RDBMS. 2PC có tính data consistency cao tương tự như local transaction, nhưng bị hạn chế về các datasource phù hợp, tính mở rộng, và có thể gặp vấn đề về khôi phục khi transaction manager trung tâm bị fail.
Orchestration: Một trong các service đóng vai trò là orchestrator (người điều phối) ở trung tâm, có trách nhiệm gọi các service khác cho đến khi chúng đạt đến trạng thái mong muốn hoặc thực hiện các hành động sửa sai nếu chúng fail. Orchestrator dùng local database để theo dõi, đồng thời chịu trách nhiệm khôi phục các lỗi liên quan đến trạng thái transaction.
Choreography: Một phương pháp thay thế cho orchestration, khi các service tham gia giao dịch trao đổi các event với nhau mà không thông qua một điểm điều phối tập trung nào. Mỗi service thực hiện local transaction của mình, publish event để kích hoạt các local transaction tiếp theo của service khác. Mỗi thành phần của hệ thống tham gia việc ra quyết định về workflow của transaction, thay vì dựa vào một trung tâm điều phối như orchestration.
Parallel Pipeline: Cũng giống như choreography, nhưng các service không thực hiện tuần tự theo event, mà sẽ thực hiện song song, với một router service sẽ nhận và forward request tới các service thông qua một message broker. Pattern này rất dễ để implement, nhưng chỉ được ứng dụng khi không có ràng buộc thứ tự giữa các service.
Trong hệ thống phân tán với hàng chục dịch vụ, sẽ không có cách tiếp cận duy nhất nào tốt cho mọi trường hợp. Chúng phải được kết hợp và ứng dụng cho từng ngữ cảnh khác nhau. Điều quan trọng là lựa chọn chiến lược có chủ ý với lí do phù hợp, và thực hiện nó. Mời các bạn đọc bài viết gốc để tìm hiểu thêm.
Trong 10 năm gần đây, hệ thống trí tuệ nhân tạo mang lại độ chính xác cao nhất, ví dụ như: hệ thống nhận diện giọng nói trên điện thoại thông minh, hay phần mềm dịch tự động của Google, đều bắt nguồn từ một kĩ thuật có tên là deep learning. Deep learning thực tế là tên gọi mới cho một cách tiếp cận tên là neural network, kỹ thuật này đã trải qua lịch sử 70 năm nhiều thăng trầm.
Neural network là một kỹ thuật Machine Learning, trong đó máy tính sẽ học làm một tác vụ nào đó thông qua việc phân tích dữ liệu huấn luyện. Thông thường, các ví dụ cần phải được dán nhãn thủ công từ trước. Một hệ thống nhận diện vật thể có thể được truyền vào, ví dụ: hàng nghìn bức ảnh đã được dán nhãn về ô tô, nhà cửa, cốc cà phê, để tìm ra các hình mẫu thị giác mà có sự tương quan nhất định tới một nhãn cụ thể.
Được thiết kế dựa trên não người, một neural network có thể bao gồm hàng nghìn hoặc hàng triệu node tính toán đơn giản được kết nối chằng chịt với nhau. Hầu hết các mạng neuron ngày nay được tổ chức thành nhiều lớp, và có tính "feed forward" - tức là dữ liệu sẽ chỉ được truyền qua các lớp theo một chiều nhất định. Mỗi một node có thể được kết nối với nhiều node ở lớp phía trước để nhận dữ liệu và với nhiều node ở lớp kế tiếp để truyền dữ liệu. Với mỗi kết nối truyền đến, node sẽ gán cho nó một con số được gọi là "trọng số" (weight). Khi mạng neuron hoạt động, mỗi node sẽ nhận các mẫu dữ liệu thông qua các kết nối và sẽ nhân chúng với trọng số tương ứng. Sau đó nó sẽ cộng tất cả các phép nhân đó để ra được kết quả là 1 số duy nhất. Nếu con số này dưới ngưỡng giá trị, node sẽ không truyền dữ liệu sang lớp kế tiếp. Ngược lại, nếu kết quả vượt ngưỡng giá trị thì node sẽ kích hoạt (fire), có nghĩa là sẽ truyền đi kết quả đó cùng với các kết nối đầu ra cho lớp kế tiếp.
Trong quá trình huấn luyện, ban đầu tất cả trọng số và giá trị ngưỡng sẽ được gán cho các giá trị ngẫu nhiên. Dữ liệu huấn luyện sẽ được cho vào lớp ở đáy - lớp input, và sẽ truyền đi qua các lớp tiếp theo, thực hiện phép nhân, cộng theo nhiều cách phức tạp khác nhau cho tới khi chạm tới lớp đầu ra cuối cùng ở trạng thái đã biến đổi hoàn toàn. Trong quá trình huấn luyện, trọng số và giá trị ngưỡng sẽ liên tục được điều chỉnh cho tới khi dữ liệu huấn luyện với các nhãn trùng nhau sẽ luôn cho ra kết quả giống nhau.
Mời các bạn đọc bài viết gốc để có thêm thông tin về lịch sử phát triển của Neural Network/Deep Learning cũng như các câu hỏi còn bỏ ngỏ về tính lý luận của công nghệ này.
Góc Distributed System
ETCD Lease
Trong ETCD tồn tại dịch vụ lock giúp đảm bảo mutual exclusion giữa các ETCD server nodes và clients. Dịch vụ lock này hoạt động dựa trên phương pháp lease, cụ thể là:
Khi client yêu cầu truy vấn vào resource, trước hết nó sẽ gửi lease request.
Server sẽ trả lại lease token, kèm time-to-live (TTL).
Client giữ lease sẽ được quyền access vào resource trong khoảng thời gian TTL.
Quá TTL server sẽ revoke lease token.
Tuy nhiên có vài vấn đề của TTL-based lease-based locking như sau:
TTL dựa trên physical clock, do đó sẽ không tránh khỏi clock skew giữa client và server (ví dụ server revoke lease token rồi nhưng client vẫn nghĩ là nó còn giữ lease hợp lệ).
Lease state giữa client và server không đồng bộ, ví dụ client bị crash và server đã revoke lease rồi, tới khi client restart nó vẫn nghĩ là nó còn giữ lease hợp lệ.
ETCD đưa ra kĩ thuật version number validation. Ý tưởng cơ bản là versioning lease token và kiểm tra version có hợp lệ hay không với mỗi truy vấn vào resource từ phía client.
Lease khi được 1 etcd server grant sẽ được đồng bộ với các server khác qua Raft. Bạn tìm hiểu thêm về ETCD lease implementation trong bài viết sau đây
Góc Database
Implementing the Netflix Media Database
Vào năm 2018, Netflix giới thiệu về hệ thống Netflix Media Database (NMDB), một cơ sở dữ liệu được xây dựng để chứa các dữ liệu quan trọng về media của họ, đặc biệt là về media metadata. Hệ thống này được thiết kế với mục tiêu là có thể đáp ứng được nhiều nhu cầu từ các ứng dụng ở Netflix, và đồng thời đảm bảo được các tính năng như là: multi-tenant, tính mở rộng (scalable) cao, hỗ trợ lưu lượng read/write lớn, và hỗ trợ các lệnh truy vấn với gần như thời gian thực (near realtime).
Ở biểu đồ trên, chúng ta có thể thấy rằng NMDB được chia ra thành nhiều mảng sau đây:
Ở mảng hạ tầng, NMDB tận dụng Object Store (S3), Cassandra, distributed lock service, và ElasticSearch để quản lý dữ liệu và index
Do cần phải sử dụng nhiều hệ thống ở mảng hạ tầng, các kỹ sư ở Netflix đã tạo thêm một lớp để điều phối các hệ thống này, và đồng thời hỗ trợ các quy trình làm việc căn bản như là Create, Read, Update, Delete (CRUD) cho dữ liệu ở tất cả các hệ thống
Ở mảng cuối cùng, NMDB sẽ có các dịch vụ để tiếp nhận và xử lý các requests từ client. Các dịch vụ này sẽ đảm nhận một vai trò riêng như là: xác thực các lệnh viết và đọc, quản lý và truy vấn dữ liệu từ Cassandra, quản lý và truy vấn index từ ElasticSearch, …
Để hiểu rõ hơn cách mà các kỹ sư ở Netflix xây dựng hệ thống Netflix Media Database này như thế nào, các bạn có thể tham khảo thêm ở bài viết sau đây
Góc Lập Trình
Đề tuần này:
Cho một chuỗi s, hãy tìm độ dài của subsequence (chuỗi con) palindromic dài nhất của s.
Một subsequence là một chuỗi có thể được dẫn xuất từ một chuỗi khác bằng cách xóa một số hoặc không có phần tử nào mà không thay đổi thứ tự của các phần tử còn lại.
Ví dụ 1:
Input: s = "bbbab"
Output: 4
Giải thích: Chuỗi con palindromic dài nhất là "bbbb".
Ví dụ 2:
Input: s = "cbbd"
Output: 2
Giải thích: Chuỗi con palindromic dài nhất là "bb".
Các bạn có thể thử sức tại đây: https://leetcode.com/problems/longest-palindromic-subsequence/
Lời giải tuần trước:
Có hai cách duyệt cây phổ biến là DFS và BFS. Ở bài này, ta cần trả về nút ngoài cùng bên phải tại từng độ sâu tương ứng, vì vậy BFS có vẻ sẽ phù hợp. Tuy nhiên, thay vì dùng queue, ta chỉ cần lưu lại tất cả các nút tại độ sâu tương ứng. Các bạn có thể tham khảo lời giải mẫu tại đây:https://pastebin.com/wNfqHSsv
Độ phức tạp của giải thuât time complexity là O(n) với n là tổng số nút, bởi ta phải duyệt qua tất cả các nút. Space complexity là O(n).
Ta có thể tối ưu space complexity xuống O(D) với D là chiều rộng (diameter) của cây, D có giá trị tối đa là n/2, trong trường hợp cây là complete binary tree.
Tech Talks
React 2014 : Erik Meijer - What does it mean to be Reactive?
Trong video này, Erik Meijer (tác giả và đồng tác giả của nhiều programming language, library) nói về bản chất của Reactive programming. Với cách dẫn dắt dí dỏm, thông minh, ông thay đổi cách nhìn của người xem về những khái niệm đơn giản như getter, setter, Enumerator, từ đó giải thích tại sao Reactive Programming đơn giản chỉ là một cách nhìn mới về những khái niệm cũ. Bên cạnh đó ông cũng giới thiệu một số khái niệm hàn lâm nhưng không khô khan như duality, Monad.
Code & Tools
https://r2dbc.io/ - The Reactive Relational Database Connectivity (R2DBC) project brings reactive programming APIs to relational databases.
https://github.com/provectus/kafka-ui - A free, open-source web UI to monitor and manage Apache Kafka clusters.
Góc Sponsors
Fossil Vietnam, formerly Misfit, is the Center of Excellence for Wearables Research & Development of Fossil Group. We’re an innovative team that designs and engineers world-class wearables products that touch the lives of millions of people. We take pride in being innovators who are pushing the boundaries of fashion and technology.
Why you’ll love working at Fossil Vietnam
Opportunities to work with global Tech giants.
Attractive salary and performance bonus twice a year.
Premium healthcare for employees and family, even on probation.
15 days of Annual leave and 2 days of Volunteer leave, even on probation.
All tools you need: Mac/Windows, iOS/Android, Testing devices/State-of-the-art wearables, you name it.
Welcome watch after probation.
You’ll get food to get fit, we’ll take care of it all.
Join us, and you’ll contribute to the development of next-generation wearable technology that makes a difference in people’s everyday lives. View all featured positions.
Keep in touch
Quotes
“An estimate is the most optimistic prediction that has a non-zero probability of coming true . . . Accepting this definition leads irrevocably toward a method called 'what’s-the-earliest-date-by-which-you-can’t-prove-you-won’t-be-finished estimating.'"
- Tom DeMarco (1982)