#227 - Thiết kế retry consumer cho Kafka
Chào các bạn độc giả của Grokking Newsletter.
Mời các bạn truy cập vào Grokking Knowledge Graph để đọc lại toàn bộ các bài viết của Grokking Newsletter nhé: https://knowledge.grokking.org/
Tại website này, chúng tôi đã tổng hợp toàn bộ 1000 bài viết của newsletter từ trước tới nay, ngoài ra các bài viết đều được phân loại, gán nhãn theo từng chủ đề quan trọng. Qua đó chúng tôi hy vọng các bạn có thể dễ dàng tìm kiếm được những bài viết mà mình quan tâm.
Mọi ý kiến đóng góp xin gửi về newsletter@grokking.org
Trong số này, chúng ta cùng tìm hiểu về:
Cách LinkedIn xây dựng API versioning cho Marketing APIs của họ
Thiết kế retry consumer cho Kafka
Chi tiết về C++ dequeue
Lời giải bài Making File Names Unique
Ngoài ra các bạn vẫn có thể tiếp tục đặt mua ấn phẩm Dijkstra tập 2 tại đây nhé.
Những bài viết hay
Under the hood: How we built API versioning for LinkedIn Marketing APIs
(by sonnv)
Tại LinkedIn, mục tiêu của nhóm phát triển API là tạo ra một nền tảng có thể xây dựng, vận hành và phát triển việc kinh doanh của LinkedIn trên phạm vi toàn cầu.
Các nhà phát triển sử dụng Marketing API của LinkedIn để xây dụng giải pháp mới và sáng tạo bổ sung cho giải pháp Marketing của LinkedIn, nhằm cho phép họ đạt được mục tiêu nhiều hơn.
Đi cùng với sự phát triển của business, đội ngũ kĩ sư mong muốn nền tảng của họ ngày càng được hoàn thiện hơn qua những lần thay đổi và tăng khả năng mở rộng của hệ thống. Tuy nhiên sự thay đổi và phát triển liên tục đòi hỏi phải đảm bảo hệ thống không được gián đoạn và các hoạt động của khách hàng vẫn diễn ra như bình thường, hệ thống API hiện tại không đảm bảo được sự phát triển bền vững và khả năng mở rộng.
Vì vậy nhóm LinkedIn Marketing API bắt đầu xây dựng một hệ thống quản lý thay đổi API với tài liệu phong phú và một bảng thay đổi chi tiết, mời bạn đọc cùng tìm hiểu chi tiết qua bài viết sau.
Retrying consumer architecture in the Apache Kafka
(by quangle)
Apache Kafka là một hệ thống phân tán streaming dữ liệu phổ biến được ứng dụng để xây dựng các pipelines data, message brokers, v.v.. đảm bảo khả năng scale up lớn.
Một trong những vấn đề thường gặp khi triển khai với Kafka là quá trình xử lý message bị lỗi đến từ nhiều lý do như sai format message, lỗi ràng buộc database. Để giải quyết bài toán trên, cơ chế retry message lỗi là một giải pháp được lựa chọn.
Với 3 hướng tiếp cận của cơ chế retry được tác giả đề xuất lần lượt như:
Simple retry logic: thử lại quá trình xử lý message với một độ trễ cố định.
Non-blocking retry logic: Với Kafka, việc xử lý message không thành công sẽ ngăn chúng ta không thể di chuyển đến offset của message kế để tiếp tục xử lý được. Vì không thể để một message lỗi lại ảnh hưởng toàn bộ hệ thống, ta có thể đẩy chúng vào trong một topic khác chẳng hạn như retry_topic. Sau đó các consumers sẽ xử lý các message lỗi trong topic retry này mà không ảnh hưởng đến các message khác. Nếu trong quá trình xử lý các message retry cũng không thành công, chúng sẽ được đẩy vào fail_topic để đánh giá thêm.
Flexible non-blocking retry logic: Cách tiếp cận trên nhìn chung khá ổn nhưng vẫn còn một số chỗ có thể cải thiện. Thay vì chỉ xử lý message retry không thành công một lần duy nhất thì đẩy vào fail topic, ta có thể thử lại chúng nhiều lần bằng cách chia ra các mốc thời gian retry tuần tự như: 5 phút, 30 phút, 1 giờ với các topic tương ứng retry_5m_topic, retry_30m_topic, retry_1h_topic. Nếu vẫn không thành công thì mới quyết định đẩy vào fail_topic.
Để tìm hiểu chi tiết hơn từng giải pháp, mời bạn đọc cùng tham khảo bài viết.
An In-Depth Study of the STL Deque Container
(by curioustien)
Trong C++, vector và deque (double-ended queue) thường có thể được dùng để làm containers cho các data structures khác như là stack, queue, priority queue, … Một trong những điểm khác biệt chính giữa 2 containers này là người dùng có thể truy vấn và viết dữ liệu ở lẫn phía trước và phía sau cho dequeue thay vì chỉ ở phía sau cho vector.
Bài viết sau đây được tác giả nói cụ thể hơn về các ưu và nhược điểm của dequeue và vector bằng cách chạy một vài benchmarks:
Khi cần đẩy nhiều dữ liệu vào dequeue và vector thì dequeue chạy tốt hơn vector do nó allocate bộ nhớ theo từng block với độ dài nhất định. Trong khi vector sẽ tăng buffer bộ nhớ ngày càng nhiều hơn dựa vào số lượng dữ liệu nó đang chứa. Do đó, chúng ta nên tận dụng
vector::reserve()
khi cần phải viết rất nhiều dữ liệu vào vector.Do dequeue được phân theo từng blocks có độ dài nhất định và không có gần nhau trên bộ nhớ so với vector, việc lấy lại bộ nhớ từ dequeue sẽ chậm hơn nhiều với vector. Chúng ta nên lưu ý điều này khi cần phải tối ưu hóa.
Góc Lập Trình
Đề ra tuần này: Max Consecutive Ones III
(by ndaadn)
Cho một chuỗi nhị phân và một số k, bạn được phép đổi nhiều nhất k số 0 thành số 1. Hãy trả lại độ dài lớn nhất của chuỗi số 1 liên tiếp mà bạn có thể tạo được.
Ví dụ:
Input: nums = [1,1,1,0,0,0,1,1,1,1,0], k = 2
Output: 6
Ta có thể đổi 2 số 0 thành số 1 như sau (số được gạch chân)
[1,1,1,0,0,1,1,1,1,1,1]
Lời giải đề bài tuần trước: Making File Names Unique
(by phucnh)
Trước hết ta cần xác định rằng: ta không thể sắp xếp lại mảng đầu vào. Ví dụ với mảng đầu vào như dưới đây, ta sẽ có kết quả hoàn toàn khác nếu thứ tự của các phần tử khác nhau.
original input = ["a", "a(1)", "a(2)", "a"]
output = ["a", "a(1)", "a(2)", "a(3)"]
Nếu ta thay đổi thứ tự của các phần tử, ta có kết quả như sau:
sorted input = ["a", "a", "a(1)", "a(2)"]
output = ["a", "a(1)", "a(1)(1)", "a(2)"]
Như vậy, để xác định xem tên thư mục đã được sử dụng hay chưa, ta có thể sử dụng Set. Nếu tên thư mục đã được sử dụng trước đó, ta tăng giá trị hậu tố lên một đơn vị, rồi tiến hành kiểm tra cho tới khi tên thư mục hoàn toàn mới. Ta có giả mã như sau: https://pastebin.com/fNTxfKT1
Với giải thuật trên, trong trường hợp mảng đầu vào chỉ chứa một giá trị (ví dụ: tất cả phần tử đều là chữ cái "a"), giải thuật có độ phức tạp thời gian lên tới O(n^2 * S)
, với n là độ dài của mảng đầu vào, S là độ dài tối đa của một phần tử.
Ta có thể tối ưu bằng cách sử dụng HashMap để lưu lại giá trị hậu tố tiếp theo như sau: https://pastebin.com/nbMc35D3
Độ phức tạp thời gian của giải thuật sẽ trở thành amortized O(n*S)
Code & Tools
rustlings - những bài tập nhỏ giúp bạn làm quen với đọc và viết Rust
BigQuery Schema Generator - tạo BigQuery schema từ JSON và CSV
Feedback
Bạn đánh giá nội dung số newsletter này thế nào?
(1 = Rất tệ / 5 = Rất tốt)
(Việc đánh giá của các bạn là rất quan trọng, sẽ giúp chúng tôi liên tục cải thiện nội dung newsletter tốt hơn)
Grokking mang lại cho các bạn những kiến thức mới mẻ và hữu ích thông qua:
Tech Talk: Là một hoạt động thường xuyên của Grokking từ những ngày đầu thành lập. Tại đây các diễn giả chia sẻ kiến thức xoay quanh Computer Science và Software Engineer. Các buổi Tech Talk đều được record và upload lên kênh youtube.
Knowledge Graph: Tập hợp những nguồn kiến thức phong phú với hơn 1000 bài viết chọn lọc, các đầu sách, khóa học, v.v… Các bài viết đều được gán nhãn để giúp bạn đọc dễ dàng tìm kiếm.
Webinar: Là chương trình kết nối các kỹ sư Việt Nam và các kỹ sư đang làm việc tại các công ty công nghệ hàng đầu thế giới.
Dijkstra: Một ấn phẩm được xuất bản bởi các thành viên của Grokking. Với những bài viết đào sâu vào kỹ thuật và kiến thức khoa học máy tính.
Kipalog: Nền tảng chia sẻ kiến thức dành cho các lập trình viên.
Newsletter: Những bài viết hay về công nghệ sẽ được gửi tới bạn hàng tuần qua email.
Chúc các bạn sẽ tìm được nhiều điều mới mẻ khi đến với Grokking và xin hẹn gặp lại các bạn vào tuần sau.
Quotes
A good programmer is someone who always looks both ways before crossing a one-way street.
– Doug Linder