#138 - Tại sao Apache Kafka lại nhanh?
TechTalk #38 - Languages, Technologies, Architectures - different components that make a high performance system
Để xây một ngôi nhà vững chắc thì cần rất nhiều thứ như nền móng, tường, cột, … Tương tự, để xây một một hệ thống phần mềm vững chắc thì cần sự kết nhiều yếu tố như ngôn ngữ lập trình, công nghệ và kiến trúc phù hợp, …
Trong Grokking TechTalk #38 lần này, các bạn sẽ được giới thiệu quá trình phân tích hiệu năng của một hệ thống và những phương pháp giải quyết sử dụng từ thiết kế kiến trúc hệ thống cho tới kỹ thuật lập trình.
Ngoài ra bạn cũng có cơ hội tìm hiểu thêm về những stack công nghệ mà một công ty có lượng người dùng lớn như LINE Technology Vietnam thường sử dụng.
Các bạn nào đang ở Hà Nội cố gắng dành thời gian để tham dự Techtalk đầu tiên của Grokking được tổ chức offline ở thủ đô nhé.
- Thời gian: 09:00 - 12:00 Thứ 7, 26/09/2020
- Link đăng ký: http://bit.ly/grokking-techtalk-38-registration
- Địa điểm: LINE Technology Vietnam - Tầng 20, Tòa nhà TNR, 54A Nguyễn Chí Thanh, quận Đống Đa, Hà Nội
Những bài viết hay
What makes Apache Kafka so Fast? — medium.com
Kafka hỗ trợ một nền tảng thông lượng cao (throughput), phân tán (distributed), có khả năng chịu lỗi (fault-tolerant) với việc phân phối thông điệp có độ trễ thấp. Vậy Kafka được thiết kế như thế nào để đạt được độ trễ thấp như vậy?
Hãy cùng tìm hiểu 3 cơ chế giúp Kafka đạt được điều này:
Batch data và Compression: tin nhắn có thể được viết và đọc vào queue theo batch. Giả sử chúng ta có 1000 tín nhắn, việc viết hoặc đọc 1000 tin nhắn 1 lần theo batch chắc chắn sẽ nhanh hơn nhiều nếu thực hiện cùng thao tác 1000 lần, mỗi lần 1 tin nhắn. Ngoài ra khi việc xử lý theo batch giúp ta có thể nén tin nhắn lại, giúp giảm dung lượng dữ liệu qua network.
Horizontally Scaling: Kafka có khả năng có hàng nghìn partition cho một topic duy nhất, trải rộng giữa hàng nghìn máy. Điều này giúp Kafka có thể xử lý tải rất lớn.
Gửi tin nhắn có độ trễ thấp: Hầu hết các hệ thống dữ liệu truyền thống sử dụng bộ nhớ truy cập ngẫu nhiên (RAM) để lưu trữ dữ liệu, vì RAM cung cấp độ trễ cực kỳ thấp. Tuy nhiên RAM rất đắt đỏ đặc biệt khi lượng dữ liệu là vô cùng lơn. Vì vậy, Kafka không dùng RAM để có thể gửi tin nhắn có độ trễ thấp, mà sử dụng 2 thiết kế là Sequential I/O và Zero Copy Principle.
Sequential I/O: Kafka sử dụng filesystem để lưu trữ và cache tin nhắn. Chúng ta biết rằng disk chậm hơn nhiều so với RAM trong thời gian tìm kiếm thông tin được lưu trữ. Kỹ thuật Sequential I/O giải quyết điều này với thiết kế append-only log, một cấu trúc dữ liệu có thứ tự. Mỗi khi producer gửi tin nhắn đến queue thành công, offset của tin nhắn đó sẽ được gửi lại. Giá trị offset tăng dần từ giá trị ban đầu 0 và giúp producer biết được nơi cần viết tin nhắn khi cần. Tương tự, consumer luôn lưu trữ giá trị offset giúp việc tìm kiếm tin nhắn cần đọc trở nên nhanh hơn nhiều.
Zero Copy Principle: Để hiểu về kĩ thuật này, chúng ta cần hiểu điều gì xảy ra khi 1 ứng dụng muốn gửi dữ liệu từ disk qua 1 network. Theo cách truyền thống, dữ liệu sẽ được Kernal đọc và đẩy đến ứng dụng. Ứng dụng tiếp tục viết dữ liệu vào socket để sau đó gửi qua network. Với Zero Copy Principle, Kernal sẽ đọc dữ liệu trực tiếp dữ liệu từ disk và viết thẳng vào socket. Điều này giúp giảm thiểu các tác vụ trung gian và tối ưu hoạt động của Kernal.
Function in JavaScript Has More Secrets Than You Think — medium.com
Khái niệm function (hàm) đã quá quen thuộc với tất cả các developer, nhưng bạn đã thật sự hiểu và sử dụng nó đúng cách?
Trong bài viết sau tác giả chia sẻ một vài kỹ thuật hữu ích trong quá trình sử dụng hàm. Mặc dù bài viết dùng ngữ cảnh javascript, các kiến thức này cũng có thể áp dụng cho các ngôn ngữ khác.
Các kỹ thuật được đề cập trong bài viết:
Pure Function: luôn trả về cùng một kết quả cho một hoặc một tập đối số đầu vào và không có side effects (đọc thêm bài đọc để biết side effects là gì).
Higher-Order Function: nhận đối số là một hoặc nhiều hàm và trả về kết là một hàm khác. Sử dụng Higher-Order Function giúp chúng ta viết code linh hoạt, ngắn gọn và hiệu quả hơn.
Function Caching: mọi người đều biết cache là một kĩ thuật để nâng cao hiệu suất, function caching cũng có cùng mục đích như vậy. Ý tưởng là sau khi thực thi hàm kết quả được cached lại với key là các đối số đầu vào, ở lần thực thi tiếp theo, kết quả ở lần thực thi trước đó sẽ được trả về ngay mà ko cần phải thực thi lại.
Lazy Function: trong một số trường hợp một vài đoạn code chỉ cần được thực thi ở lần chạy đầu tiên, những lần sau đó sẽ được bỏ qua. Đó chính là ý tưởng của lazy function.
Function Currying: thay vì chấp nhật tất cả các đối số một lần, function currying sẽ chấp nhật đối số thứ nhất và trả về một function chấp nhận đối số thứ 2, cứ tiếp tục như vậy cho đến đối số cuối cùng, ví dụ add(1,2,3) có thể viết dạng function currying add(1)(2)(3).
Function Compose: thông thường ở những tác vụ phức tạp chúng ta sẽ tách ra thành nhiều hàm nhỏ hơn, sẽ có một hàm chịu trách nhiệm thực thi các hàm nhỏ đó ví dụ func3(func2(func1(x))), để tránh trường hợp này chúng ta có thể viết kiểu compose ví dụ XYZ = compose(func2, func1) và thực thi XYZ().
Understanding the Event Loop, Callbacks, Promises, and Async/Await in JavaScript — www.digitalocean.com
Chắc hẳn các bạn đã biết Javascript một ngôn ngữ đơn luồng (single thread), tuy nhiên điều này liệu có đồng nghĩa với việc mọi tác vụ của Javascript đều phải được thực thi dưới hình thức đồng bộ?
Câu trả lời là không, là một ngôn ngữ đơn luồng nhưng cơ chế hoạt động của Javascript trên browser vẫn hỗ trợ việc xử lý bất đồng bộ (asynchronous) nhờ sự kết hợp của các thành phần như Stack (còn được gọi là call-stack), WebAPIs, Callback Queue và Event Loop.
Stack: giữ trạng thái của function đang được thực thi, sau khi câu lệnh đã được thực thi xong, nó sẽ được xoá khỏi Stack.
WebAPIs: gồm các apis được cung cấp bởi browser như DOM, AJAX, hay Timeout
Callback Queue: sau khi WebAPIs thực xong một tác vụ nào đó nếu tác vụ đó có callback function, thì callback function này sẽ được đẩy vào callback queue.
Event Loop: nhiệm vụ của event loop là kiểm tra xem trong Callback Queue callback function sẽ bốc ra và đẩy vào Stack nếu Stack đang trống
Đọc thêm bài viết sau để biết thêm chi tiết cách thức hoạt động của các thành phần này.
Góc Distributed System
Hệ thống phân tán (distributed system) là một trong các từ khoá quan trọng trong nhiều năm trở lại đây khi nhu cầu về mặt business đòi hỏi các hệ thống công nghệ ngày càng lớn với nhiều servers cùng vận hành một lúc. Việc phối hợp nhiều servers đặt ra nhiều bài toán mà các kỹ sư cần phải giải quyết, trong đó kinh điển nhất là bài toán đồng thuận (consensus).
Tại sao việc đồng thuận giữa các server lại là một bài toán khó trong các hệ thống phân tán? Hãy cùng thử khảo sát thông qua một phiên bản trực quan của bài toán này như sau:
Một số vị tướng (process) quyết định lên kế hoạch phối hợp tấn công một vùng đất. Họ hiểu rằng việc tấn công chỉ có thể thành công nếu tất cả cùng tham gia. Vấn đề là họ đóng quân ở nhiều vị trí khác nhau, và phương tiện liên lạc chỉ là truyền miệng. Họ cần phải thống nhất thời điểm cùng đồng loạt tấn công. Các vị tướng ở lân cận nhau có thể giao tiếp với nhau thông qua người truyền tin.
Nếu tất cả người truyền tin đều đáng tin cậy thì toàn bộ vị tướng có thể gửi tin lẫn nhau. Như vậy sau 1 vài round truyền tin, họ có thể thống nhất thời điểm tấn công.
Tuy nhiên, việc truyền tin luôn có thể bị thất bại vì nhiều lý do như: người truyền tin bị đối phương bắt giữ, người truyền tin bị chậm, thông điệp bị sửa đổi, ... Vậy làm sao các vị tướng có thể đưa ra được quyết định chính xác?
Đã có nhiều thuật toán được đưa ra để giải quyết bài toán đồng thuận này, trong đó có hai thuật toán được ứng dụng rộng rãi là Paxos và Raft.
Trong hai thuật toán này, Raft được ra đời sau với nhiều điều chỉnh về cách mô tả thuật toán, các quyết định thiết kế (được cho là tối ưu hơn) so với Paxos. Nhưng liệu có phải Raft luôn tốt hơn Paxos không? Điểm khác biệt của hai dòng thuật toán này là gì? Mời các bạn đọc bài báo dưới đây để hiểu thêm về cách so sánh hai thuật toán này (link).
Góc Database
Ở cùng chuyên mục Góc Database của số newsletter kỳ trước, chúng ta đã cùng đọc chính chia sẻ của Eric, tác giả đề xuất định lý CAP. Trong bài báo kỳ trước, Eric đã chia sẻ những suy nghĩ của mình về chính định lý CAP và những ngộ nhận phổ biến xung quanh nó.
Trong kỳ này, mời các bạn cùng tham khảo bài viết khác của tác giả Martin Kleppmann cũng chia sẻ về chủ đề tương tự để có cái nhìn thấu đáo hơn về định lý CAP.
Link bài báo: link.
Code & Tools
When DRY Doesn’t Work, Go WET. It’s okay if you repeat yourself
Sonyflake - A distributed unique ID generator inspired by Twitter's Snowflake
Sponsor
We’ve built an engineering and AI powerhouse in bustling southern Vietnam, where we tackle AI’s biggest challenges in the public safety space. With cameras that depict truth, automated reporting and evidence management that will triple the amount of time officers can spend serving their communities, and Smart Weapons that protect life in the moment of conflict, Axon has revolutionized the world of public safety - and by working here, you can contribute every day to the mission to protect life.
Opening Jobs:
Quote
Before software can be reusable it first has to be usable.
– Ralph Johnson