Khái niệm nền tảng: Đồng bộ hóa và Định danh
Hệ thống phân tán cần hai cơ chế cốt lõi để đảm bảo hoạt động ổn định:
- Đồng bộ hóa: Giải quyết vấn đề đồng nhất trạng thái giữa các node (ví dụ: xử lý xung đột khi nhiều node cùng cập nhật tài nguyên)
- Định danh: Cung cấp cơ chế định danh duy nhất và định vị tài nguyên (ví dụ: cấp phát ID duy nhất cho dịch vụ, định tuyến yêu cầu tới instance phù hợp)
Công cụ phổ biến
- ZooKeeper (ZK): Sử dụng mô hình nút phân cấp
- Etcd: Dùng không gian khóa-giá trị phẳng
- Consul & Nacos: Tích hợp thêm phát hiện dịch vụ
Cơ chế định danh toàn cục
Phát sinh ID duy nhất
Hai phương pháp chính:
- Thuật toán Snowflake: Kết hợp ID máy chủ + timestamp + số tuần tự
- Sử dụng ZK/Etcd: Tận dụng tính năng nút tuần tự
// Ví dụ tạo ID bằng ZK
ZooKeeper zooKeeperClient = new ZooKeeper("localhost:2181", 3000, null);
String path = zooKeeperClient.create("/id/job-", "data".getBytes(),
ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.SEQUENTIAL);
long uniqueID = Long.parseLong(path.substring(path.lastIndexOf('/') + 1));
Đăng ký và phát hiện dịch vụ
| Công cụ | Cơ chế |
|---|---|
| ZooKeeper | Tạo nút tạm thời trong cấu trúc phân cấp |
| Etcd | Kết hợp khóa-giá trị với Lease (thuê bao) |
Cơ chế đồng bộ hóa
Giao thức nhất quán
So sánh ZAB (ZooKeeper) và Raft (Etcd):
- ZAB: Tập trung vào thứ tự giao dịch toàn cục
- Raft: Sao chép nhật ký với cơ chế đa số đồng thuận
Phân phối sự kiện
Hai mô hình xử lý sự kiện:
- ZK Watcher: Kích hoạt đơn lần - cần đăng ký lại
- Etcd Watch: Kết nối luồng liên tục - không cần đăng ký lại
Khóa phân tán
Cơ chế triển khai:
- ZK: Dùng nút tuần tự tạm thời
- Etcd: Kết hợp khóa với Lease
// Ví dụ khóa phân tán với Curator
InterProcessMutex distributedLock = new InterProcessMutex(curatorClient, "/locks/resource");
if (distributedLock.acquire(10, TimeUnit.SECONDS)) {
// Xử lý đoạn mã quan trọng
distributedLock.release();
}
Triển khai thực tế
Tâm điểm cấu hình
Giải pháp dùng Etcd:
- Ứng dụng đọc cấu hình từ khóa
/config/app/db_url - Giám sát thay đổi bằng Watch
- Áp dụng revision để xử lý phiên bản cấu hình
Lên lịch công việc
Dùng ZK để đồng bộ thực thi tác vụ:
- Tạo nút tạm thời
/tasks/sync - Node giành quyền tạo nút sẽ thực thi
- Node còn lại theo dõi và cạnh tranh khi nút bị xóa
Tối ưu và lưu ý
- Tránh hiện tượng "sự kiện đàn cừu" (herd effect) trong ZK
- Phân vùng namespace theo ứng dụng
- Áp dụng caching cấu hình cục bộ
- Dùng công cụ quản lý client (Curator, etcdctl)
Đặc điểm triển khai
Hệ thống đồng bộ luôn được triển khai dưới dạng cụm độc lập vì:
- Đảm bảo tính nhất quán tập trung
- Tránh phụ thuộc vào vòng đời ứng dụng
- Dễ dàng mở rộng và bảo trì