Quy trình viết dữ liệu vào chỉ mục Elasticsearch và tối ưu hóa quy trình này

Mục lục

    1. Quy trình xử lý tài liệu của Lucene
  • 1.1. Quy trình thêm tài liệu
  • 1.2. Quy trình xóa tài liệu
    1. Tối ưu hóa quy trình viết - Hiển thị tìm kiếm thời gian thực gần
  • 2.1. Tư duy cải thiện quy trình
  • 2.2. Cài đặt khoảng thời gian refresh
    1. Tối ưu hóa quy trình viết - Thực hiện việc lưu trữ lâu dài
  • 3.1. Quy trình lưu tài liệu vào đĩa cứng
  • 3.2. Phục hồi dữ liệu dựa trên translog và điểm commit
    1. Tối ưu hóa quy trình viết - Thêm các tệp segment lớn
  • 4.1. Các vấn đề tồn tại
  • 4.2. Quy trình thực hiện merge
  • 4.3. Tối ưu hóa các cấu hình merge
  • 4.4. Sử dụng接口 optimize
  • Tài liệu tham khảo
  • Quyền tác giả
  1. Quy trình xử lý tài liệu của Lucene =====================

Lucene lưu trữ và quản lý dữ liệu index dưới dạng các đoạn (segment).

Trong Lucene,一旦 được tạo, bộ chỉ mục倒排 không thể thay đổi. Để thêm hoặc sửa đổi tài liệu, phải tái tạo lại toàn bộ bộ chỉ mục倒排, điều này gây ra các giới hạn về số lượng dữ liệu mà một index có thể chứa hoặc tần suất cập nhật index.

Để cập nhật bộ chỉ mục倒排 mà không làm thay đổi tính không đổi của nó, Lucene đã giới thiệu một ý tưởng mới: tăng thêm các index bổ sung để phản ánh các thay đổi mới nhất thay vì viết lại toàn bộ bộ chỉ mục倒排.

Nhờ đó, mỗi phiên bản bộ chỉ mục倒排 từ đầu tiên đều được truy vấn và kết quả được hợp nhất sau đó. Tài liệu bị xóa vẫn có thể được tìm thấy trong các kết quả truy vấn.

1.1. Quy trình thêm tài liệu

① Viết dữ liệu vào bộ đệm (bộ đệm trong bộ nhớ);

② Thực hiện commit: Dữ liệu trong bộ đệm được cam kết như một đoạn index mới vào bộ nhớ cache của hệ thống tệp;

③ Đoạn index được cache sau đó đượcFlush sang hệ thống đĩa cứng thông qua hàm fsync;

④ Tất cả các đoạn được viết vào đĩa cứng đều được ghi vào điểm commit và lưu trên đĩa;

⑤ Mở đoạn index mới để sẵn sàng cho các truy vấn外部;

⑥ Xóa bộ đệm hiện tại và đợi nhận các tài liệu mới.

Giải thích:

(a) fsync là một hàm hệ thống Unix được sử dụng để cam kết dữ liệu từ bộ đệm vào hệ thống tệp. Ở đây đã được tối ưu hóa để Flush các đoạn index từ cache sang đĩa cứng.

(b) Mỗi Shard đều có một điểm commit, chứa thông tin về các đoạn index đã được cam kết thành công vào đĩa cứng.

1.2. Quy trình xóa tài liệu

① Thực hiện thao tác delete: Tìm đoạn index chứa tài liệu cần xóa;

② Điểm commit chứa một tệp .del, ghi lại các đoạn index nào và các tài liệu nào bị xóa;

③ Khi số lượng tài liệu trong .del đủ lớn, Elasticsearch sẽ thực hiện xóa vật lý, xóa hoàn toàn các tài liệu này.

  • Truy vấn trong khi xóa:

Truy vấn các đoạn index, sau đó loại bỏ các tài liệu được đánh dấu là deleted từ kết quả trả về.

  • Cập nhật trong khi xóa:

Đánh dấu tài liệu cũ là deleted, sau đó thêm tài liệu mới vào đoạn index mới. Truy vấn có thể trả về phiên bản cũ của tài liệu, nhưng các phiên bản này sẽ bị loại bỏ nhờ vào thông tin từ .del.

  1. Tối ưu hóa quy trình viết - Hiển thị tìm kiếm thời gian thực gần ==================

2.1. Tư duy cải thiện quy trình

(1) Vấn đề của quy trình hiện tại:

Dữ liệu mới cần đợi fsync Flush các đoạn index sang đĩa cứng mới có thể được truy vấn. Điều này gây ra chi phí cao và làm giảm thời gian thực.

(2) Cải thiện quy trình:

① Viết dữ liệu vào bộ đệm;

② Không đợi bộ đệm đầy, mà cam kết dữ liệu thành đoạn index mới vào cache của hệ thống tệp sau một khoảng thời gian nhất định (mặc định 1s);

③ Mở đoạn index mới ngay lập tức để cho phép truy vấn;

④ Xóa bộ đệm hiện tại và đợi nhận các tài liệu mới.

Quá trình này được gọi là refresh, một quy trình nhẹ nhàng hơn, bỏ qua fsync.

2.2. Cài đặt khoảng thời gian refresh

Elasticsearch refresh mỗi Shards mỗi giây, cho phép tìm kiếm thời gian thực gần với khoảng thời gian mặc định là 1s.

(1) Refresh thủ công:

# Refresh tất cả các chỉ mục:
POST _refresh
# Refresh một chỉ mục cụ thể: 
POST employee/_refresh

(2) Cài đặt khoảng thời gian refresh:

# Tạo chỉ mục với khoảng thời gian refresh 1 phút:
PUT employee
{
    "settings": {
        "refresh_interval": "1m"
    }
}
# Cài đặt khoảng thời gian refresh cho chỉ mục hiện có:
PUT employee/_settings
{
    "refresh_interval": "10s"
}

(3) Tắt refresh tự động khi tạo chỉ mục lớn và bật lại sau đó:

# Tắt refresh tự động:
PUT employee/_settings
{
    "refresh_interval": -1 
} 
# Bật refresh mỗi giây:
PUT employee/_settings
{
    "refresh_interval": "1s"
}
  1. Tối ưu hóa quy trình viết - Thực hiện việc lưu trữ lâu dài ==================

Elasticsearch sử dụng nhật ký giao dịch (translog) để ngăn ngừa việc mất dữ liệu.

3.1. Quy trình lưu tài liệu vào đĩa cứng

① Viết dữ liệu vào bộ đệm và translog;

② Refresh định kỳ:

(a) Cam kết dữ liệu bộ đệm thành đoạn index mới vào cache hệ thống tệp; (b) Mở đoạn index mới để truy vấn;

③ Xóa bộ đệm và đợi nhận dữ liệu mới;

④ Translog ngày càng lớn;

Flush định kỳ (mặc định mỗi 30 phút) hoặc khi translog đạt kích thước tối đa (mặc định 512MB):

(a) Viết dữ liệu bộ đệm sang đoạn index mới và cam kết vào cache; (b) Mở đoạn index mới; (c) Xóa bộ đệm; (d) Flush translog sang đĩa cứng thông qua fsync; (e) Cập nhật điểm commit và ghi vào đĩa; (f) Xóa translog hiện tại và tạo translog mới.

Translog cũng được sử dụng để cung cấp CRUD thời gian thực.

Khi truy vấn theo id, Elasticsearch kiểm tra translog trước khi truy vấn các đoạn index để đảm bảo kết quả mới nhất.

3.2. Phục hồi dữ liệu dựa trên translog và điểm commit

(1) Cấu hình translog:

Flush = Cam kết các ghi chép translog sang đĩa + Cập nhật thông tin commit point + Xóa translog cũ.

Elasticsearch mặc định flush mỗi 30 phút hoặc khi translog đạt 512MB.

Các cấu hình liên quan:

# Số lượng thao tác sau đó cần flush, mặc định không giới hạn:
index.translog.flush_threshold_ops

# Kích thước tệp translog cần flush, mặc định 512MB:
index.translog.flush_threshold_size

# Khoảng thời gian giữa các lần flush, mặc định 30 phút:
index.translog.flush_threshold_period

# Khoảng thời gian kiểm tra và flush translog, mặc định 5s:
index.translog.interval

(2) Phục hồi dữ liệu khi lỗi:

① Thao tác thêm/xóa/sửa thành công khi đoạn index được cam kết vào Primary và Replica Shards.

Translog chứa các ghi chép thay đổi từ commit point cuối cùng đến thời điểm hiện tại.

③ Khi Elasticsearch bị lỗi hoặc khởi động lại, hệ thống tải các đoạn index từ commit point và tái tạo các thay đổi từ translog để đảm bảo tính nhất quán.

(3) Refresh translog bất đồng bộ:

Để tăng tốc độ, Elasticsearch có thể cho phép refresh translog không cam kết dữ liệu sang đĩa cứng ngay lập tức:

PUT employee/_settings
{
    "index.translog.durability": "async",
    "index.translog.sync_interval": "5s"
}

Tuy nhiên, điều này có thể làm giảm tính nhất quán và an toàn dữ liệu.

  1. Tối ưu hóa quy trình viết - Thêm các tệp segment lớn ===========================

4.1. Các vấn đề tồn tại

Quy trình refresh mỗi giây tạo ra các đoạn index mới, gây ra việc truy vấn chậm do phải đọc nhiều đoạn.

Giải pháp: Merge các đoạn index thành các đoạn lớn hơn để cải thiện hiệu năng truy vấn.

Quy trình này được xử lý bởi một thread riêng, không ảnh hưởng đến việc tạo các đoạn mới.

Trong khi merge, các tài liệu bị xóa sẽ được xóa vật lý.

4.2. Quy trình merge

① Chọn các đoạn có kích thước tương đương để merge thành đoạn lớn;

② Cam kết đoạn mới vào đĩa cứng;

③ Cập nhật điểm commit, bao gồm đoạn mới và loại bỏ các đoạn cũ;

④ Mở đoạn index mới để truy vấn;

⑤ Xóa các đoạn index cũ.

4.3. Tối ưu hóa các cấu hình merge

Merge là một thao tác tiêu tốn tài nguyên CPU và IO. Do đó, Elasticsearch cung cấp các cấu hình để giới hạn tốc độ merge.

(1) Giới hạn tốc độ merge:

Cấu hình indices.store.throttle.max_bytes_per_sec mặc định là 20MB. Đối với các server xử lý大量 dữ liệu, cần tăng giá trị này lên 100MB hoặc hơn:

PUT _cluster/settings
{
    "persistent" : {
        "indices.store.throttle.max_bytes_per_sec" : "100mb"
    }
}

(2) Số lượng thread merge:

Recommendation: số thread bằng một nửa số lõi CPU. Nếu性能磁盘 kém, có thể giảm số thread để tránh tắc:

PUT employee/_settings
{
    "index.merge.scheduler.max_thread_count" : 8
}

(3) Các chính sách khác:

# Đoạn dưới kích thước này sẽ được merge, mặc định 2MB:
index.merge.policy.floor_segment

# Số đoạn tối đa được merge một lúc, mặc định 10:
index.merge.policy.max_merge_at_once

# Số đoạn tối đa được merge một lúc khi gọi optimize, mặc định 30:
index.merge.policy.max_merge_at_once_explicit

# Đoạn vượt kích thước này không tham gia merge, mặc định 5GB:
index.merge.policy.max_merged_segment

4.4. Sử dụng接口 optimize

Khi số lượng đoạn index vượt quá giới hạn mặc định, cần merge các đoạn thành một đoạn lớn để tiết kiệm tài nguyên:

# Merge các đoạn thành một đoạn duy nhất:
POST employee/_optimize?max_num_segments=1

# Thực hiện qua commandline:
curl -XPOST http://ip:5601/employee/_optimize?max_num_segments=1

Optimize không giới hạn tài nguyên, không nên sử dụng cho các chỉ mục đang hoạt động (nóng). Nên sử dụng cho các chỉ mục cũ ít thay đổi như nhật志.

Thẻ: Elasticsearch lucene index segment refresh

Đăng vào ngày 2 tháng 7 lúc 16:18