0

Elasticsearch Bài học 7: Shard & Replica - Chìa khóa của High Availability và Khả năng Scale out

Khi dữ liệu của một hệ thống chạm mốc hàng trăm gigabyte (như log hệ thống microservices) hoặc hàng triệu bản ghi (sản phẩm E-commerce), một máy chủ vật lý dù mạnh đến đâu cũng sẽ hết dung lượng ổ cứng hoặc cạn kiệt RAM khi thực thi truy vấn tìm kiếm.

Elasticsearch giải quyết bài toán này không phải bằng cách nhồi nhét vào một siêu máy chủ, mà bằng cách "băm nhỏ" dữ liệu ra nhờ cơ chế Shard (Phân đoạn) và bảo vệ nó bằng Replica (Bản sao).

Đây là hai khái niệm nền tảng giải thích vì sao Elasticsearch có thể mở rộng lưu trữ vô hạn và không bao giờ sập khi một server bị cháy.

1. Primary Shard: "Băm nhỏ" để Scale-out (Mở rộng ngang)

Như đã đề cập ở Bài 6, Index chỉ là một khái niệm logic. Thực thể vật lý thực sự chứa dữ liệu dưới ổ cứng của Elasticsearch được gọi là Shard (chính xác hơn, mỗi Shard là một engine tìm kiếm Apache Lucene hoàn chỉnh và độc lập).

Khi bạn tạo một Index, Elasticsearch sẽ chia Index đó thành nhiều Primary Shard (Phân đoạn gốc).

  • Cách hoạt động: Nếu bạn có một Index chứa 500GB dữ liệu và cấu hình 5 Primary Shards, Elasticsearch sẽ chia đều dữ liệu, mỗi Shard chứa ~100GB. Nếu cụm của bạn có 5 Node (Server), mỗi Node sẽ gánh 1 Shard. Bạn vừa chia 5 lần áp lực lưu trữ và tính toán!

  • Quy tắc tử huyệt: Số lượng Primary Shard phải được khai báo lúc khởi tạo Index và KHÔNG THỂ thay đổi sau đó.

Tại sao không thể thay đổi số lượng Primary Shard? Bởi vì thuật toán định tuyến (Routing) dữ liệu của Elasticsearch dựa vào một công thức toán học cố định: shard_num = hash(_routing) % num_primary_shards

(Trong đó _routing mặc định là ID của Document). Nếu bạn thay đổi biến số num_primary_shards (từ 5 lên 6 chẳng hạn), kết quả của phép chia lấy dư (%) sẽ thay đổi toàn bộ. Khi bạn tìm kiếm lại một Document cũ, Elasticsearch sẽ mò đến sai Shard và trả về kết quả "Không tìm thấy". Muốn đổi số Primary Shard, cách duy nhất là tạo Index mới và copy dữ liệu sang (Reindex - sẽ học ở Bài 22).

2. Replica Shard: Phòng thủ và Tăng tốc đọc (High Availability)

Nếu dữ liệu bị băm ra 5 Primary Shard nằm ở 5 Node khác nhau, chuyện gì xảy ra nếu 1 Node đột ngột bốc cháy hoặc đứt cáp mạng? Toàn bộ Index sẽ hỏng vì mất 1/5 dữ liệu gốc.

Đó là lúc Replica Shard (Phân đoạn bản sao) ra tay. Replica là một bản copy giống hệt từng byte của Primary Shard.

  • Quy luật sinh tồn: Elasticsearch không bao giờ đặt một Primary Shard và Replica của chính nó trên cùng một Node. (Vì nếu Node đó chết, cả gốc lẫn bản sao đều bốc hơi).

  • Khác biệt với Primary Shard: Bạn có thể thêm hoặc bớt số lượng Replica bất cứ lúc nào mà không làm gián đoạn hệ thống (Zero-downtime).

Lợi ích kép của Replica:

  1. Phòng thủ (High Availability): Nếu Node chứa Primary Shard chết, Master Node lập tức "thăng chức" (Promote) Replica Shard ở một Node khác lên làm Primary Shard mới chỉ trong vài mili-giây. Dữ liệu hoàn toàn an toàn.

  2. Tăng tốc độ đọc (Read Scale): Khi một request tìm kiếm bay vào, Coordinating Node có thể gửi request đó đến Primary Shard HOẶC Replica Shard. Càng có nhiều Replica, hệ thống càng chịu được nhiều traffic tìm kiếm cùng lúc (rất hữu ích cho các trang E-commerce mùa Sale).

3. Kịch bản thực chiến: Khi Server "đột tử"

Hãy hình dung một Cluster có 3 Node (Node 1, 2, 3). Bạn tạo một Index với 3 Primary Shards (P0, P1, P2) và 1 Replica (Tức là mỗi Primary có 1 bản sao: R0, R1, R2). Tổng cộng có 6 mảnh ghép.

  • Trạng thái bình thường (Green):

    • Node 1 giữ: P0, R1

    • Node 2 giữ: P1, R2

    • Node 3 giữ: P2, R0

  • Sự cố (Đứt cáp Node 1): Cụm mất Node 1 (mất P0 và R1). Trạng thái cụm lập tức chuyển sang Red (vì thiếu Primary Shard 0).

  • Phục hồi Tự động - Bước 1: Master Node phát hiện P0 mất, nhưng nó biết R0 đang nằm ở Node 3. Nó lập tức biến R0 thành P0 mới. Hệ thống phục hồi khả năng đọc/ghi đầy đủ, trạng thái chuyển sang Yellow (vì lúc này P0 và P1 không còn Replica).

  • Phục hồi Tự động - Bước 2: Master Node ra lệnh copy dữ liệu để tạo ra các Replica mới bù đắp vào chỗ thiếu, phân bổ đều trên Node 2 và 3. Khi copy xong, cụm trở về Green.

Tất cả quá trình này diễn ra hoàn toàn tự động ở background, API backend của bạn thậm chí không cảm nhận được hệ thống vừa mất đi 1/3 phần cứng.

4. Best Practices: "Chén thánh" Sizing Shard

Rất nhiều kỹ sư mắc sai lầm khi cấp phát hàng chục Shard cho một Index bé tí. Hãy nhớ, mỗi Shard là một tiến trình Lucene, nó tốn RAM, tốn file descriptor, và làm Master Node mệt mỏi khi phải quản lý trạng thái.

  • Không tạo Shard quá nhỏ: Đừng tạo 5 Shards cho một Index chỉ có 1GB dữ liệu. Hãy gom lại thành 1 Primary Shard. Khuyến cáo tối đa 20 Shard trên mỗi 1GB Heap Space của RAM.

  • Giới hạn dung lượng lý tưởng:

    • Với dữ liệu Log / Time-series (Ghi nhiều): Một Shard nên dao động từ 30GB - 50GB.

    • Với dữ liệu E-commerce (Tìm kiếm nhiều): Một Shard nên giữ dưới 20GB để truy vấn load nhanh nhất vào RAM.

Đến đây, bạn đã nắm trọn kiến trúc bên ngoài (Phân tán, Shard, Node). Đã đến lúc chúng ta "mổ bụng" một Shard để xem bên trong nó lưu dữ liệu kiểu gì mà tìm kiếm văn bản lại có thể nhanh gấp hàng nghìn lần MySQL.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí