Elasticsearch là gì
Elasticsearch chắc hẳn là nhiều người đã biết, nhưng để bài viết trơn tru, cứ phải có cái introduction cho nó dài. Elasticsearch là cơ sở dữ liệu (database) (từng) dành để lưu trữ text (document) là chính, dựa trên một engine nổi tiếng là lucene. Nói là “từng” vì hiện tại elasticsearch được dùng cho cả những ứng dụng thời thượng như là time series data (lưu dữ liệu là các “point” thay vì document) chứ không chỉ dừng lại cho text nữa.
Trong Elasticsearch thì dữ liệu được biểu diễn dưới dạng JSON và có thể dễ dàng truy vấn thông qua REST API cũng như native API (thông qua thư viện). Điểm thú vị của elasticsearch nằm ở chỗ Distributed: Dữ liệu của elasticsearch được phân tán đều trên các node (primary shard / replica shard) và được tự động phân chia lại khi thêm/xoá node đã có. Việc này khiến cho Elasticsearch rất dễ dàng để scale up/down.
Mô hình dữ liệu của ES:
Về cơ bản thì sẽ có 2 loại node chính trong ES:
- Master node: Node này có nhiệm vụ đứng mũi chịu sào, chịu trách nhiệm điều hành anh em làm việc (coordinate), cũng như nhận một số trọng trách quan trọng như thêm, xoá index… Khi master node chết thì anh em còn lại sẽ họp lại và tìm ra thằng mới dựa trên một thuật toán gọi là Paxos.
- Data node: Thằng này là culi, chuyên bốc vác dữ liệu, ai bảo gì làm nấy, có trách nhiệm lưu trữ là chính.
Tuy nhiên distributed cũng khiến cho việc vận hành trở nên painful hơn, nhiều khi do bug của việc cooperate giữa các node, hay là do các hoàn cảnh không dự đoán trước được như server gặp mưa, server gặp bão, cá mập cắn cáp… Ngoài ra một số design của elasticsearch (hay cũng như nhiều database khác) khiến cho nó có thể chết không dự đoán trước được do hết memory hay gặp phải query nặng hơn nó có thể chịu được.
Để vận hành đỡ painful thì việc quan trọng nhất chính là monitoring, tức là nắm được elasticsearch cluster của bạn đang hoạt động thế nào mà không cần phải nhìn log hay là các kiến thức cao siêu mà không phải ai cũng biết. Và cuối cùng chúng ta cũng đén được phần chính của bài viết: chúng ta cần monitoring “cái gì” để biết về sức khoẻ của elasticsearch cluster?
Những metrics cần xem khi monitoring ES
Search performance
Đây là một trong những chỉ số quan trọng nhất khi mà chức năng chính của ES là .. tìm kiếm. Những chỉ số có thể lấy được từ ES liên quan đến search performance gồm có
Total number of queries | indices.search.query_total | Throughput |
Total time spent on queries | indices.search.query_time_in_millis | Performance |
Number of queries currently in progress | indices.search.query_current | Throughput |
Total number of fetches | indices.search.fetch_total | Throughput |
Total time spent on fetches | indices.search.fetch_time_in_millis | Performance |
Number of fetches currently in progress | indices.search.fetch_current | Throughput |
Để hiểu hơn những chỉ số trên thì chúng ta cần hiểu trước về việc: Elasticsearch thực hiện việc “tìm kiếm” thế nào? Khi có một request về tìm kiếm thì đầu tiên request sẽ được gửi đến một data node bất kì chữa data của một index nào đó. Sau đó thì node này sẽ gửi request đến tất cả các node xung quanh mà chứa shard của index đang tìm, và nhận kết quả từ các node xung quanh, việc này được gọi là Fetching.
Theo như bảng ở trên thì chúng ta sẽ cần theo dõi các yếu tố chính dưới đây:
- Query Load : dựa vào “số lượng” query hiện tại đang được thực hiện, qua đó xem cluster có bị quá tải không
- Query Latency : dựa vào query time, chúng ta có thể biết cluster mất bao nhiều lâu để trả về một request
- Fetch Latency : nếu fetch tốn quá lâu, thì khả năng cao sẽ là do disk hay network có vấn đề
Index performance
Nếu coi tìm kiếm là thao tác “read” thì index chính là thao tác “write”. Để có performance tốt nhất thì các database thường tiết kiệm việc phải ghi dữ liệu vào disk (fsync) thông qua buffer, tức là lưu tạm ở memory trước, đợi nhiều nhiều rồi ghi vào disk cả thể. Elasticsearch cũng vậy, việc này thể hiện ở diagram dưới đây:
Nhìn vào 2 diagram ở trên chúng ta cần chú ý đến 2 thao tác là Refresh và Flush. 2 thao tác này dựa trên một đơn vị gọi là “Segment”. Bạn nào từng làm việc với các hệ thống database (Postgres, cassandra, influxdb) thì sẽ hiểu rằng có các đơn vị dữ liệu không thay đổi được (immutable) là rất quan trọng trong việc tạo ra một database với high write throughput. Việc này dựa trên idea chính là, cứ write đã, đúng sai tính sau (việc đúng sai tính sau thể hiện bằng thao tác “merge” được thực hiện ở background). Ở đây thì “Segment” chính là đơn vị dữ liệu không thay đổi (immutable data) của elastic search.
Một segment được tạo mới thông qua Refresh và được ghi vào đĩa + merge thông qua Flush. Flush sẽ được trigger khi memory đến giới hạn, hoặc sau một khoảng cách thời gian nào đó (khoảng sau mỗi 30 phút).
Để theo dõi các thông số liên quan đến index thì có các chỉ số dưới đây
Total number of documents indexed | indices.indexing.index_total | Throughput |
Total time spent indexing documents | indices.indexing.index_time_in_millis | Performance |
Number of documents currently being indexed | indices.indexing.index_current | Throughput |
Total number of index refreshes | indices.refresh.total | Throughput |
Total time spent refreshing indices | indices.refresh.total_time_in_millis | Performance |
Total number of index flushes to disk | indices.flush.total | Throughput |
Total time spent on flushing indices to disk | indices.flush.total_time_in_millis | Performance |
Từ những con số trên các bạn có thể hiểu ra được
- Index latency: thông qua index_total và index_time_in_millis thì bạn có thể thấy ES tốn bao nhiêu thời gian cho việc indexing , và đang phải chịu tải là bao nhiêu request.
- Flush latency : thông qua flush.total_time_in_millis thì bạn có thể thấy được latency của thao tác Flush. Nếu latency quá cao, thì có khả năng bạn đang gặp phải vấn đề về disk, hoặc là flush size quá lớn.
JVM metrics
Elasticsearch được build trên java. Vận hành một hệ thống java mà không hiểu về JVM thì coi như bạn toi chắc rồi. Để monitoring JVM system thì việc kiểm soát Memory và GC là 2 cái quan trọng nhất. Đặc biệt memory là cái tối quan trọng khi mà một query nặng có thể dẫn đến memory vượt quá kiểm soát và JVM sẽ lăn ra chết, hay là trở nên unresponsive. Khi nhìn vào heap thì quan trọng nhất là xem heap percent, tức là trong XXGB memory đã được cấp phát cho JVM, thì bao nhiêu % đã và đang được sử dụng.
Bên cạnh đó thì việc nhìn vào GC (mặc dù có nhìn thì cũng không làm được gì vì GC nằm ngoài tầm kiểm soát của bạn) cũng khá có ích để phán đoán việc khi ES cluster của bạn trở nên chậm chạp thì liệu có phải do ES bug không :v. ES team cũng khuyến cáo người dùng đừng có cố thay đổi GC option default: https://www.elastic.co/guide/en/elasticsearch/guide/current/_don_8217_t_touch_these_settings.html
Host metrics
Host metrics là những metrics thể hiện sự khoẻ mạnh của machine nói chung. Nó bao gồm những thông số như diskSpace, CPU usage , IO utilization. Như đã nói ở trên thì việc disk chậm, CPU bị starve cũng đều ảnh hưởng đến chức năng tìm kiếm rất lớn (tất nhiên rồi :v), vậy nên việc theo dõi những thông số này một cách chặt chẽ cũng giúp ích rất nhiều trong việc trouble shooting cũng như dự đoán trước về performance downgrade của ES.
Cluster health
Những thông số tôi đã nói ở trên hầu hết thể hiện sự khoẻ mạnh của một node trong toàn thể cluster. Vậy làm thế nào để biết được sự khoẻ mạnh “tổng thể” của toàn bộ cluster?
Cluster status (green, yellow, red) | cluster.health.status | Other |
Number of nodes | cluster.health.number_of_nodes | Availability |
Number of initializing shards | cluster.health.initializing_shards | Availability |
Number of unassigned shards | cluster.health.unassigned_shards | Availability |
Quan trọng nhất, và cũng dễ hiểu nhất chính là “Cluster status”.
- Green: khoẻ mạnh, không vấn đề gì
- Yellow: Một hoặc một vài replica shard đột nhiên biến mất, và nếu nó tiếp tục biến mất nữa, bạn sẽ mất dữ liệu khi tìm kiếm (có thể hiểu yellow là threshold trước khi dữ liệu tìm kiếm không còn toàn vẹn nữa )
- Red: Một hoặc một vài primary shard biến mất, điều này có nghĩa là chắc chắn kết quả search của bạn sẽ không toàn vẹn, sẽ thiếu data.
Bên cạnh cluster status thì Initializing and unassigned shards cũng khá quan trọng, nó thể hiện các shard mà đang được khởi động , hoặc chưa được assigned cho master, nếu con số này không về 0 không một nhanh chóng, chứng tỏ rằng cluster của bạn đang ở trạng thái rất thiếu ổn định.
Làm thế nào để monitoring?
Như vậy là chúng ta đã nắm được là : cần phải xem gì, nhưng chúng ta vẫn chưa đề cập đến việc: làm thế nào để xem các thông số đó. Elasticsearch cung cấp cho chúng ta tất cả các thông số ở trên thông qua HTTP GET một cách rất dễ dàng, dựa vào endpoint /_nodes/_local/stats
Đây là ví dụ khi tôi vào một node bất kì với url : node-name/_nodes/_local/stats
Để lưu dữ liệu lại và xem dưới dạng graph, bạn có thể sử dụng những service hiện có như datadog, hay là sử dụng solution có sẵn như prometheus + elasticsearch_exporter
Kết luận
Việc tìm hiểu xem một hệ thống middleware xem cần monitoring những gì và hiểu rõ về từng metrics phải monitoring sẽ giúp chúng ta có thêm nhiều kiến thức rât bổ ích về internal của middleware đó. Trong bài tiếp theo tôi sẽ nói về monitoring metrics của mysql, đợi năm sau nhé :P.
Reference