Get in touch
or send us a question?
CONTACT

LÀM SAO ĐỂ THIẾT KẾ HỆ THỐNG PHỤC VỤ HÀNG TRIỆU NGƯỜI DÙNG?

Tại sao thiết kế hệ thống hàng triệu người dùng lại khó?

Thiết kế một hệ thống cho 1, 2 người dùng, chạy trên máy local vô cùng đơn giản. Tuy nhiên, một bài toán dễ đến mấy, khi scope lên đến tầm hàng triệu người dùng cũng sẽ trở thành một bài toán lớn và khó hơn rất nhiều lần.

Tại sao vậy? Lấy ví dụ nhé, một con server cùi có thể chịu được 100 request mỗi giây. Khi lượng request lên đến 10000 thì có thể nâng cấp server xịn hơn. Nhưng khi lượng request lên đến 1-2 triệu thì không thể nâng cấp server được nữa, mà phải thiết kế sao cho nhiều server chạy cùng lúc.

Hoặc đơn thuần như việc sắp xếp dữ liệu, với 1000 entry thì chạy trong nháy mắt, nhưng với chục triệu, trăm triệu entry thì có thể chạy đến hàng tiếng, lúc này ta phải lựa chọn thuật giải tối ưu. Vấn đề này liên quan tới scalability (khả năng mở rộng của hệ thống).

Mặt khác, không phải developer nào cũng có cơ hội để giải quyết bài toán scalability. Với các ứng dụng nhỏ,những dự án outsource, ít người đôi khi chỉ cần dùng một số giải pháp đơn giản là đã giải quyết được.

Ở các công ty lớn như Facebook, Uber, Google, đây là bài toán bắt buốc phải giải. Ở Việt Nam chắc sẽ có một số công ty lớn như Zalo, Lozi, Tiki, Thế Giới Di Động mới cần giải quyết vấn đề scalability này.

Ba yếu tố quan trọng của một hệ thống

Khi thiết kế một hệ thống phục vụ hàng triệu người dùng, ta cần để ý 3 yếu tố quan trọng nhất: Performance, Availability, và Scalability:

  • Performance:  Tốc độ phản hồi của hệ thống, được đo bằng đơn vị thời gian, có thể là giây hoặc mili giây. Hệ thống hoạt động càng nhanh thì người dùng làm được nhiều việc hơn, đem lại lợi nhuận cao hơn. Hệ thống mà quá chậm thì sẽ không có ai sử dụng.
  • Availability: Chỉ khả năng hoạt động của hệ thống vào mọi thời điểm, được đo bằng uptime. Ví dụ như trong 100 ngày, hệ thống hoạt động 99 ngày còn 1 ngày die thì uptime là 99/100 = 99%.
    • Uptime của các hệ thống lớn như Facebook, Google, Uber phải luôn >99%, vì chỉ cần ngưng hoạt động vài phút là các công ty sẽ thiệt hại từ vài nghìn cho tới vài triệu đô.
    • Hôm trước phỏng vấn ở Agoda, anh Director chia sẻ 1 giây Agoda kiếm được 1000 đô. Bum bum bum 3s là 3000 đô. Do đó hệ thống mà sập cỡ 5-10 phút là thiệt hại sẽ… hơi bị bự.
  • Scalability: Khả năng mở rộng của hệ thống. Liệu khi có đông user hơn thì hệ thống có thể mở rộng (scale) được không? Việc scale có thể thực hiện dễ dàng, nhanh chóng hay không? Chi phí scale như thế nào?
    • Ví dụ lượng người dùng tăng gấp 10, ta chỉ cần tăng gấp 2 hoặc gấp 5 lượng server là phục vụ được, hệ thống có scalability cao. Tuy nhiên, nếu ta phải tăng gấp 100, gấp 200 lượng server, hoặc không thể thêm server để phục vụ chừng đó người dùng, hệ thống có scalability thấp.

Rất khó để đảm bảo 3 yếu tố này! May thay, đây là bài toàn đã được hàng chục công ty lớn giải, do đó chúng ta có một số phương pháp, thiết kế sẵn có để giải quyết vấn đề này!

Các hệ thống của Google, Linkedin, Facebook phải phục vụ hàng trăm triệu người dùng

Các thiết kế thường dùng cho hệ thống lớn

1. Đảm bảo perfomance

  • Cân bằng tải với Load Balancer: Load Balancer là một thiết bị (phần cứng hoặc phần mềm) cho phép cân bằng tải đến nhiều server.
    • Giả sử ta có 1 server có thể phục vụ 1000 người. Để phục vụ 10000 người, ta có thể chạy 10 server. Người dùng sẽ không trực tiếp truy cập tới server, mà chỉ truy cập tới load balancer. LB sẽ điều tiết, cân bằng lượng tải trên 10 server này.
Load balancer để cân bằng tải
  • Phân tán dữ liệu với Content Delivery Network (CDN): CDN là một mạng lưới các server được phân bố trên nhiều khu vực.
    • Giả sử server thiend*a để ở Mĩ, mỗi khi bạn truy cập đến thiend*a, bạn sẽ phải kết nối tới server bên Mĩ, khá là chậm. Với CDN, dữ liệu sẽ được để ở Mĩ, Việt Nam, Lào, Cam.
    • Khi bạn kết nối đến thiend*a, bạn sẽ kết nối tới server gần nhất (Việt Nam), tốc độ sẽ nhanh hơn nhiều. CDN thường chỉ chứa các dữ liệu tĩnh, ít thay đổi như media (video, ảnh, nhạc), file (CSS, JS)
Cách thức hoạt động của CDN
  • Caching: Cache là một kĩ thuật để tăng tốc độ đọc dữ liệu, bằng cách lưu dữ liệu sẵn vào cache server để tăng tốc độ đọc ở những lần sau.
    • Ví dụ mỗi lần gọi API hoặc Database mất 10s, ta chỉ gọi lần đầu và lưu kết quả vào cache. Ở những lần sau, đọc kết quả từ cache chỉ mất 0.5s thôi.

2. Đảm bảo Availability

  • Master/Slave: Thay vì chỉ chạy 1 server, ta chạy 2 hoặc nhiều hơn. 1 server chính gọi là master, các server còn lại là slave. Khi master có vấn đề (sập nguồn hay crash), một slave sẽ được chỉ định để lên thay thế master.
  • Replication: Thường được kết hợp chung với Load Balancer. Code của ứng dụng sẽ được deploy lên nhiều server. Khi có 1 server die, load balancer sẽ chuyển request sang server khác, đảm bảo request vẫn được thực hiện.
Kiến trúc Mát Tơ/Sờ Leo

3. Đảm bảo scalability

  • Vertical Scaling: Tăng sức mạnh phần cứng cho server bằng cách… lắm thêm RAM, lắm thêm chip, thay ổ cứng bằng ổ SSD.
    • Cách này khá nhanh và dễ thực hiện (Nếu dùng AWS hoặc Azure chỉ việc đổi config là xong, 30 giây). Nhược điểm của cách làm này là: phần cứng luôn có một giới hạn, phần cứng càng mạnh thì giá càng… trên trời nên chỉ có thể mở rộng đến một giới hạn nhất định
  • Horizontal Scaling: Thay vì tăng sức mạnh cho 1 server, ta thêm nhiều server vào hệ thống và chạy cùng lúc.
    • Cách này làm cho thiết kế phức tạp hơn, nhưng bù lại ta có thể dùng phần cứng rẻ tiền lắp thêm vào, khả năng mở rộng hầu như không giới hạn (Google File System sử dụng hướng này, data center hàng nghìn con server linux loại rẻ).
Vertical và Horizontal Scaling
  • Với application server (server chứa code): Cần đảm bảo code ở server là stateless (không lưu trạng thái). Ta chỉ cần chạy vài chục đến vài trăm server (server farm), các server này đều ẩn sau load balancer. Load balancer sẽ điều tiết tải lên các server này. Nếu lượng người dùng tăng, chỉ việc thêm server là xong.
  • Với database server: Với database thì mọi chuyện phức tạp hơn nhiều, ta không thể chạy database ở nhiều máy vì dữ liệu có thể sẽ bị bất đồng bộ.
    • Cho các ứng dụng thuần read/ít write (blog, trang tin tức,…) ta có thể dùng thiết kế master/slave : 1 server master để read/write, nhiều server slave chỉ để đọc. Khi người dùng cần đọc thông tin từ database, ta có thể đọc từ master hoặc một trong các slave. Khi cần ghi dữ liệu vào database, ta ghi vào master, sau đó đồng bộ dần qua các slave.
    • Cho các ứng dụng có lượng read/write nhiều như nhau (Agoda, Facebook), ta có thể áp dụng cách sharding. Chia database thành các mẫu shard nhỏ (theo IP, theo địa điểm vật lý của người dùng,…). Các database NoSQL (MongoDB, Cassandra) đều hỗ trợ sharding kiểu này.