Elasicsearch Kullanım Tecrübemiz #3

Neslihan Esra Altınışık
Apinizer
Published in
5 min readNov 11, 2020

Serinin bu yazısında, kendi indeksimiz için shard ve disk boyutu ne olmalıdır ve Elasticsearch’de kontrol etmek gereken konfigurasyon ayarları nelerdir sorularına cevap aradık.

Seri İçeriği⚪️ Elasticsearch Kullanım Tecrübemiz #1
Aşama 1: Couchbase & InfluxDb & Elasticsearch hangisi bizim için doğru karar?
Aşama 2: Bizim için doğru Elasticsearch ayarı nedir?
⚪️️ Elasticsearch Kullanım Tecrübemiz #2
Aşama 3: Performans Testleri
🔵️ Elasticsearch Kullanım Tecrübemiz #3
Aşama 4: Shard ve Disk Boyutu
Aşama 5: Önemli Kontroller

Kendi dokümanımızın yapısı, Durum3'de yer alan durum3Kosul1 indexi ile aynıdır. Müşteri ihtiyacına göre günlük 15 milyon dokümanın tutulacağı indeksin boyutu~33.1gb ‘dır. İlk olarak shard’ın boyutu ve sayısının etkili olduğu işlemlere bakalım ;

  • Rebalance: Elasticsearch shardlar üzeriden veriyi küme içinde dağıtır. Mesela node’dan bir hata alındığında, Elasticsearch veriyi yeniden dengelemek (rebalance) için shardları taşırken, ağ ve disk performansı kadar shard sayısı ve shard boyutuda önemlidir.
  • Merge: Disk üzerinde immutable olan segmentlerin sayısı artıkça, segmentler birleştirilir. Bu işlem sürecinde özellikle disk üzerindeki I/O işlemleri artabileceği için yoğun olarak kaynak tüketebilir. Ek olarak, küçük shardlar küçük segmentlere, küçük segmentler de shard üzerinde yükün artmasına sebep olur.
  • Forcemerge: Shard başına düşen yük, segment boyutuna ve sayısına bağlıdır. Bu yüzden küçük segmentleri büyük segmentlerle Force Merge API ile birleştirmek, ek yükü azaltabilir ve sorgu performansını artırabilir. Bu işlem pahalı olduğu için yoğun olmayan saatlerde yapılmalıdır. Bu işlemi zaman bazlı verilerde rollover yaptıktan sonra kulanışlıdır. Rollover ile veri hacmi tahmin edilemeyen çok büyük veya çok küçük shardlar kaçınmayı sağlar.
  • Sorgu performansı: Birden çok shard olduğunda, sorgu paralel olarak işlenir. Çok sayıda küçük shardların olması işlemi daha hızlı yapsa da, çok fazla görevin sıralanıp birleştirilmesi gerekir. Küçük shardlar üzerinde eşzamanlı olarak birden çok sorgunun çalıştırılması da verimi düşürür.

Bu linkteki kurallar ve ipucular baz alınarak zaman-bazlı verilerin, 20gb-40gb arasında boyuta sahip shard kullanımı yaygın olduğu söylemektedir. Diğer öneri ise node daki shard sayısı heap miktarı ile orantılı tutmak. Bu da her gb için 20 gb altında shard ayarlandığında 30 gb’lık heap’e sahip node için 600 tane shard ayarlanabilir. Bu çözüm yolunu esas alarak; günlük 15 milyon verinin tuttuğu 1 primary shard’a sahip 1 index, 33 gb yer kapladığını hesapladık. Yıllık 365 adet shard oluşup ve diskte 12tb (365*33gb) yer tutar. Yıllık oluşacak 365 shard sayısı, 600 sharddan az olduğu bu kurala uyar. Bu da bize yıllık 64 gb sistem bellekli elasticsearch node’unun , 30 gb node bellekli 1 adet olarak verir. Bu da bize yıllık 64gb sistem bellekli ve 30gb heap değerindeki 1 adet elasticsearch node’unun ihtiyacımızı karşıladığını karar verdik. 👍

Aşama 5: Önemli Kontroller

➡️ File descriptors sayısını artırma

Linux ve macOs işletim sistemleri için geçerli bir ayardır. Elasticsearch büyük miktarda File descriptors kullanılır. Tavsiye edilen değer 65.536'dur. Bizde bu şekilde ayarladık.

# Elasticsearch başlatılmadan önce root olarak 
ulimit -n 65536
# Aşağıdaki kommutlar da işletilebilir
sudo vim /etc/security/limits.conf -nofile 65536
# Max file descriptor limitini kontrol etmek için;
GET _nodes/stats/process?filter_path=**.max_file_descriptors

➡️ Swapping özelliğini kapatma

Swappping, işletim sisteminin bellek ve işlemci yönetimini sağladığı bir tekniktir. İşletim sistemi de bellek dolu olduğunda process’in devam etmesi için swap memory’i etkinleştirebilir. Bu da VM (virtual memory) tarafından belleğin page adı verilen küçük parçalara bölünmesine neden olur. Page ya da swap file hard diskte saklanır, page’in adresi de bellekte tutulur. Bu sayede page, belleğin boyutu sınırlı olduğu için uygulamanın bellekte depolanamayan fazla veriyi saklamasına izin verir.

Elasticsearch’ün JVM’i major bir garbage collection yaptığında heap’deki her sayfaya bakar. Eğer page’lerden biri diskten götürüldüğünde, tekrar belleğe alınması gerekir. Bu, diskin daha çok çalışmasına sebep olur. Swapping’i kapatmanın bir çok yolu var. Bunlardan biri de Elasticsearch üzerinden ayarlanır. Eğer memory lock aktifleştirildiyse, JVM’in başarılı olaran uygulayıp uygulamadığı kontrol edilmelidir.

# geçici olarak swapping i kapatma 
sudo swapoff -a
# kalıcı olarak swap işlemini devre dışı bırakmak için
/etc/fstab dosyası düzenlenir.
# ve swap ile başlayan yorum satırı silinmelidir. Bu işlemi yaparken sunucunun programları çalıştırabilecek yeterli boyutta RAM olduğuna emin olunmalıdır. # /swapfile none swap sw 0 0 # /config/elasticsearch.yml dosyasına aşağıdaki özellik eklenir. Varsayılan değeri false’dur.
bootstrap_memory_lock:true
# Memory lock'u kontrol etmek için;
GET _nodes?filter_path=**.mlockall

➡️ Sanal bellek kullanımı

Index, mmapfs (memory mapping file system) dosya sistemine göre saklanır. mmapfs’de varsayılan olarak gelen depolama için kullanılan dosya sistemidir. Out of Memory hatasına neden olmamak için bu değer ayarlanmalıdır. Bizde bu şekilde ayarladık. 😇

# Linux üzerinde bu limiti artırmak için aşağıdaki komut root olarak çalıştırılır. 
sysctl -w vm.max_map_count=262144
# Ya da '/etc/sysctl.conf' dosyasından 'vm.max_map_count' özelliği güncellenebilir.

➡️ Kullanılmayan RAM boyutunu ayarlama

Bu link baz alınarak, önbellekleme için işletim sistemi tarafından kullanılmak üzere RAM’in en az %50'sini bulundurmak iyi bir kuraldır. Linux, file descriptor’ları yoğun olarak önbelleğe almakta daha duyarlıdır. Elasticsearch de özellikle indexleme esnasında diski çok kullanır.

# Bu komut satırından kontrol edilebilir 
free -m

➡️ Elasticsearch’ün kullanacağı heap memory boyutunun ayarlanması

Eğer heap değeri normalin altındaysa bellek vs. hatalarına neden olmaktadır. Eğer fazla verildiyse cacheleme için kullanılacağından garbage collector’i de fazla çalışmasına sebep olabilir. Bu durumda, garbage collector heap’e baskı uygulayarak cluster’ın performansının düşürür. Bu senaryolar ile başa çıkmak için güvenli bir marj değeri bırakılabilir.

Mevcut sistemdeki bellek boyutunun yarısı Elasticsearch JVM’in heap boyutuna verilmesini ve bu değerin 32 gb’ı geçmemesi önerilmektedir.

# /config/jvm.options dosyası üzerinden heap'e atanan minimum ve maksimum boyut: 30gb  
-Xms30g (Heap’in başlangıç boyut)
-Xmx30g (Heap’in maximum boyutu)

➡️ İşlemci sayısını belirtme

Elasticsearch tarafından algılanan cpu core sayısı yanlış olabilir. Bunu kontrol etmek için aşağıdaki istek yapılır.

# Kibana üzerinde yapılan istek; 
GET _nodes/os
# Cevap
{
"_nodes" : {
"total" : 1,
"successful" : 1,
"failed" : 0
},
"cluster_name" : "ApinizerEsCluster",
"nodes" : {
"HDWd7_ztRO2PbPr0joyvjw" : {
"name" : "vmi268443.contaboserver.net",
"transport_address" : "cluster_ip:9300",
"host" : "cluster_ip",
"ip" : "cluster_ip",
"version" : "7.6.0", "build_flavor" :
"default", "build_type" : "tar",
"build_hash" : "7f634e9f44834fbc12724506cc1da681b0c3b1e3",
...
"os" : {
"refresh_interval_in_millis" : 1000,
"name" : "Linux",
"pretty_name" : "CentOS Linux 7 (Core)",
"arch" : "amd64",
"version" : "3.10.0-1062.el7.x86_64",
"available_processors" : 1, "allocated_processors" : 1
},
...
}
}
}

“available_processors” ve “allocated_processors” değerlerine bakılır. 4 cpu core’un olduğu node, cluster üzerinde 1 olarak görülmektedir. Bunu düzeltmek için elasticsearch.yml dosyasına aşağıdaki alan eklenip, node yeniden başlatılmalıdır.

node.processors: 4

Varsayılım ki cluster da 5 node ve her node’un cpu core sayısı 6 ve Elasticsearch üzerinde algılanan işlemci sayısı 1 olsun. Processors değeri 6 olarak atandıktan sonra cluster 5 yerine 30 cpu core ile çalışacaktır. İşlemci sayısını doğru ayarlamak, büyük bir performans artışı sağlar.

➡️ Garbage Collector ayarı

Veri hacmi büyüdükçe performans sorunlarına neden olabilecek potansiyele sahip ve yönetilmesi önemsiz olmayan bir diğer kontroldür. Heap memory dolduğunda belirli aralıklar temizlenmesi için GC ile ilgili ayarlar yapılır.

Burada yapılan araştırmada, sürüm yükseltme sonrasında 48 cpu core’u olan makinelerin CPU kullanımı ve heap kullanımı %80-%90 oranına çıktığı görülmüş. Değerlendirmeler soncunda young ve old pool arasındaki oranın genel olarak 1:2 (33% young/66% old) veya 1:3 olması gerekirken kendi sistemlerinde bu oranın 1:14 olduğu tespit edilmiş. Bu durumun üstesinden gelmek için GC ile yapılan ayarlar aşağıdadır. Bu olayı, Elasticsearch’ün önceki sürümüyle kullanıdığında yaşanmasında dolayı bu yapılandırmayı baz aldık.

# Bu ayar /config/jvm.options dosyası üzerinden yapılır. Genel olarak bu değerlerin açıkça belirtilmemiş ise Elasticsearch başlatıldığında, JVM dinamik olarak oluşturur. Dinamik oluşturduğunda yanılmalar olabilir. -XX:+UseConcMarkSweepGC 
-XX:CMSInitiatingOccupancyFraction=75 (Heap’in doluluk oranı %75'e ulaştığında GC çalışır)
-XX:+UseCMSInitiatingOccupancyOnly
-XX:ParallelGCThreads=48 (İşlemci sayısı)
-XX:NewRatio=2 (young pool ve old pool oranlaması yapılır. Bu değer 1:2 oranı olduğunu belirtir.)
# Ya da bu komut satırı çalıştırılır. java -Xms30G -Xmx30G -XX:ParallelGCThreads=48 -XX:NewRatio=2 -XX:+UseConcMarkSweepGC -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version | egrep -i "(NewSize | OldSize | NewRatio | ParallelGCThreads)"uintx NewRatio := 2 {product}
uintx NewSize := 11095310336 {product}
uintx OldSize := 22190686208 {product}
uintx ParallelGCThreads := 48

--

--