Elasticsearch Performans Optimizasyonu: Shard ve Replica Ayarları
Elasticsearch kurulumunu tamamladınız, index’lerinizi oluşturdunuz, verilerinizi yüklüyorsunuz. Her şey güzel görünüyor. Sonra üretim ortamına geçiyorsunuz ve sistem yavaşlamaya başlıyor. Sorgular 10-15 saniye sürüyor, node’lar birbirine giriyor, cluster sağlığı sarıya dönüyor. Bu noktada bakmanız gereken ilk yer: shard ve replica ayarları.
Elasticsearch’ün performansını doğrudan etkileyen bu iki parametre, çoğu zaman varsayılan değerlerle bırakılıyor. Oysa yanlış shard sayısı, küçük bir cluster’ı bile felç edebilir. Bu yazıda gerçek dünya senaryoları üzerinden shard ve replica mantığını, nasıl ayarlanması gerektiğini ve mevcut ortamları nasıl optimize edeceğinizi detaylıca ele alacağız.
Shard ve Replica Nedir, Neden Önemlidir
Elasticsearch’te her index, shard adı verilen daha küçük parçalara bölünür. Bu parçalar fiziksel olarak Lucene index’lerinden ibarettir ve farklı node’lara dağıtılabilir. Bir index’in kaç primary shard’a sahip olacağını index oluşturulurken belirlemeniz gerekir. Çünkü bu değer sonradan değiştirilemez (reindex olmadan).
Replica ise her primary shard’ın kopyasıdır. Hem yüksek erişilebilirlik hem de okuma performansı için kullanılır. Primary shard’ı barındıran node çöktüğünde, replica otomatik olarak primary role’üne yükselir.
Temel kavramları netleştirelim:
- Primary Shard: Verinin asıl kopyasını tutan shard. Index oluşturulurken belirlenir.
- Replica Shard: Primary shard’ın kopyası. Dinamik olarak değiştirilebilir.
- Shard Allocation: Shard’ların hangi node’lara yerleştirileceğini belirleyen süreç.
- Over-sharding: Gereğinden fazla shard oluşturmak, performans sorunlarının ana nedenidir.
- Under-sharding: Çok az shard, büyük veri setlerinde paralel işleme imkânını kısıtlar.
Elasticsearch’ün kendi dokümanlarında da belirtildiği gibi, her shard bir JVM süreci ve dosya tanımlayıcı tüketir. Küçük bir 5 GB’lık index için 50 shard oluşturmak, 50 ayrı Lucene index çalıştırmak demektir. Bu gereksiz overhead, cluster’ı boğar.
Doğru Shard Sayısını Hesaplamak
Altın kural şu: bir shard, 10-50 GB arasında veri tutmalıdır. Bu aralığın dışına çıkmak sorunlara davet çıkarmaktır.
Pratik hesaplama şöyle yapılır:
Toplam veri boyutunu tahmin edin. Diyelim ki günlük 20 GB log verisi biriktiriyorsunuz ve 30 günlük veriyi tek bir index’te tutuyorsunuz. Bu 600 GB eder. 600 GB / 30 GB (hedef shard boyutu) = 20 primary shard. Eğer 1 replica tutuyorsanız toplam shard sayısı 40 olur.
Şimdi bunu cluster node sayısıyla karşılaştırın. 4 node’unuz varsa, 40 shard bu node’lara 10’ar adet dağılır. Bu makul bir dağılımdır.
Genel kurallar:
- Node başına düşen shard sayısı: Node’un heap belleği (GB) x 20 değerini geçmemeli. 30 GB heap’e sahip bir node’da maksimum 600 shard taşıyabilirsiniz.
- Küçük cluster’larda: 3 node’lu bir cluster için index başına 3 primary shard mantıklı başlangıç noktasıdır.
- Büyüyen index’ler için: Zaman bazlı index’ler (ILM ile yönetilen) kullanın.
Mevcut cluster’ınızdaki shard durumunu kontrol etmek için:
# Cluster genelindeki shard dağılımını görüntüle
curl -X GET "localhost:9200/_cat/shards?v&pretty"
# Node başına düşen shard sayısını öğren
curl -X GET "localhost:9200/_cat/allocation?v&pretty"
# Index bazında shard bilgisi
curl -X GET "localhost:9200/_cat/indices?v&h=index,pri,rep,docs.count,store.size,pri.store.size&pretty"
Index Oluştururken Shard Ayarları
Yeni bir index oluştururken shard ve replica sayısını settings bloğunda belirliyoruz:
# Log verisi için örnek index oluşturma
curl -X PUT "localhost:9200/uygulama-loglari-2024"
-H 'Content-Type: application/json'
-d '{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"refresh_interval": "30s",
"index.routing.allocation.total_shards_per_node": 2
},
"mappings": {
"properties": {
"timestamp": { "type": "date" },
"level": { "type": "keyword" },
"message": { "type": "text" }
}
}
}'
Burada birkaç önemli ayar dikkat çekiyor:
- number_of_shards: 3: 3 node’lu cluster için uygun. Her node bir primary shard taşır.
- number_of_replicas: 1: Her primary shard’ın bir kopyası olur. 3 node’da primary + replica toplam 6 shard dağılır.
- refresh_interval: 30s: Varsayılan 1 saniyedir. Indexleme yoğunsa bu değeri artırmak yazma performansını ciddi ölçüde iyileştirir.
- index.routing.allocation.total_shards_per_node: 2: Bir node’a en fazla 2 shard yerleşmesini sağlar. Hotspot oluşmasını engeller.
Mevcut Index’lerde Replica Sayısını Değiştirmek
Primary shard sayısını değiştiremezsiniz ama replica sayısını istediğiniz zaman güncelleyebilirsiniz:
# Tek bir index'in replica sayısını güncelle
curl -X PUT "localhost:9200/uygulama-loglari-2024/_settings"
-H 'Content-Type: application/json'
-d '{
"number_of_replicas": 2
}'
# Wildcard ile birden fazla index'i aynı anda güncelle
curl -X PUT "localhost:9200/uygulama-loglari-*/_settings"
-H 'Content-Type: application/json'
-d '{
"number_of_replicas": 1
}'
# Tüm index'lerin replica sayısını sıfırla (tek node test ortamı için)
curl -X PUT "localhost:9200/_all/_settings"
-H 'Content-Type: application/json'
-d '{
"number_of_replicas": 0
}'
Dikkat: Üretim ortamında replica sayısını 0 yapmayın. Bu ayar sadece tek node’lu geliştirme/test ortamları için geçerlidir. Üretimde en az 1 replica bulundurmak, hem veri güvenliği hem de okuma performansı açısından zorunludur.
Index Template ile Standart Ayarlar Tanımlamak
Her seferinde elle ayar yapmak yerine, index template kullanmak çok daha pratik bir yaklaşımdır. Özellikle Logstash veya Beats ile veri gönderiyorsanız, template olmadan her yeni index varsayılan 1 shard ile açılır.
# Composable template oluşturma (Elasticsearch 7.8+)
curl -X PUT "localhost:9200/_index_template/log-template"
-H 'Content-Type: application/json'
-d '{
"index_patterns": ["log-*", "uygulama-*"],
"priority": 100,
"template": {
"settings": {
"number_of_shards": 2,
"number_of_replicas": 1,
"refresh_interval": "10s",
"index.translog.durability": "async",
"index.translog.sync_interval": "30s"
},
"mappings": {
"dynamic_templates": [
{
"string_as_keyword": {
"match_mapping_type": "string",
"mapping": {
"type": "keyword",
"ignore_above": 256
}
}
}
]
}
}
}'
Template’de özellikle dikkat çeken iki ayar:
- index.translog.durability: async: Her write işleminin diske senkronize yazılmasını beklemek yerine asenkron yapar. Veri kaybı riskini artırır ama yazma performansı belirgin şekilde yükselir. Log verisi gibi kayıp tolere edilebilir senaryolarda tercih edilir.
- index.translog.sync_interval: 30s: Translog’un ne sıklıkla diske flush edileceğini belirler.
Shard Allocation Ayarları
Cluster büyüdükçe, hangi shard’ın hangi node’a gideceğini kontrol etmek isteyebilirsiniz. Özellikle donanım farklılıkları varsa bu kritik hale gelir.
# Node'lara etiket eklemek (elasticsearch.yml içinde veya API ile)
curl -X PUT "localhost:9200/_cluster/settings"
-H 'Content-Type: application/json'
-d '{
"persistent": {
"cluster.routing.allocation.awareness.attributes": "zone",
"cluster.routing.allocation.awareness.force.zone.values": "zone1,zone2"
}
}'
# Belirli bir index'i sadece "hot" node'lara dağıt
curl -X PUT "localhost:9200/aktif-veri-index/_settings"
-H 'Content-Type: application/json'
-d '{
"index.routing.allocation.require.node_type": "hot"
}'
# Shard rebalancing ayarlarını optimize et
curl -X PUT "localhost:9200/_cluster/settings"
-H 'Content-Type: application/json'
-d '{
"persistent": {
"cluster.routing.allocation.balance.shard": "0.45",
"cluster.routing.allocation.balance.index": "0.55",
"cluster.routing.rebalance.enable": "all"
}
}'
cluster.routing.allocation.balance.shard: Shard sayısına göre dengeleme ağırlığı. cluster.routing.allocation.balance.index: Index bazında dengeleme ağırlığı.
Gerçek Dünya Senaryosu: E-ticaret Platformu
Bir e-ticaret müşterimizin yaşadığı problemi ele alalım. Elasticsearch’te ürün katalog index’leri ve sipariş geçmişi tutuyorlar. Başlangıçta her index için varsayılan 5 primary shard, 1 replica kullanılmış. 3 node’lu cluster’da bu ayarlar şu durumu yaratmış:
- 10 farklı index x 5 primary x 2 (primary + replica) = 100 shard
- Her node 33 shard taşıyor
- Katalog index’i sadece 2 GB veri tutmasına rağmen 5 shard’a bölünmüş
- Her shard ortalama 400 MB, bu gereksiz overhead demek
Çözüm adımları:
# Önce mevcut durumu analiz et
curl -X GET "localhost:9200/_cat/shards?v&s=store:desc&pretty"
# Küçük index'leri tespit et (1 GB altı)
curl -X GET "localhost:9200/_cat/indices?v&h=index,pri,rep,store.size&s=store.size:asc&pretty"
# Katalog index'ini reindex ile yeniden oluştur
curl -X PUT "localhost:9200/urun-katalog-v2"
-H 'Content-Type: application/json'
-d '{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 1
}
}'
# Reindex işlemini başlat
curl -X POST "localhost:9200/_reindex?wait_for_completion=false"
-H 'Content-Type: application/json'
-d '{
"source": { "index": "urun-katalog" },
"dest": { "index": "urun-katalog-v2" }
}'
# Reindex durumunu takip et
curl -X GET "localhost:9200/_tasks?actions=*reindex&detailed&pretty"
Bu optimizasyon sonrasında toplam shard sayısı 100’den 42’ye düştü. Sorgu süresi ortalama %35 iyileşti. Cluster CPU kullanımı %20 geriledi.
Bulk Indexing Sırasında Performans Optimizasyonu
Büyük veri yüklemelerinde shard ve replica ayarlarını geçici olarak değiştirmek, indexleme hızını dramatik biçimde artırır:
# Büyük veri yüklemesi öncesi ayarları optimize et
curl -X PUT "localhost:9200/buyuk-veri-index/_settings"
-H 'Content-Type: application/json'
-d '{
"number_of_replicas": 0,
"refresh_interval": "-1"
}'
# Veri yüklemesi tamamlandıktan sonra ayarları geri al
curl -X PUT "localhost:9200/buyuk-veri-index/_settings"
-H 'Content-Type: application/json'
-d '{
"number_of_replicas": 1,
"refresh_interval": "1s"
}'
# Segment'leri birleştirerek arama performansını artır
curl -X POST "localhost:9200/buyuk-veri-index/_forcemerge?max_num_segments=1"
refresh_interval: -1 ayarı, otomatik refresh’i tamamen devre dışı bırakır. Bu süreçte index edilen veriler aramada görünmez ama write throughput iki ila üç kat artar. Yükleme sonrası mutlaka normal değerine döndürün.
forcemerge komutu, zaman içinde oluşan çok sayıda küçük segment’i birleştirerek sorgu performansını iyileştirir. Ancak bu işlem CPU ve disk yoğun olduğu için üretim saatlerinde çalıştırmaktan kaçının.
ILM ile Shard Yönetimini Otomatikleştirmek
Index Lifecycle Management (ILM), özellikle log ve metrik verisi için shard yönetimini otomatikleştirmenin en etkili yoludur:
# ILM policy oluştur
curl -X PUT "localhost:9200/_ilm/policy/log-lifecycle"
-H 'Content-Type: application/json'
-d '{
"policy": {
"phases": {
"hot": {
"min_age": "0ms",
"actions": {
"rollover": {
"max_size": "30gb",
"max_age": "1d"
},
"set_priority": {
"priority": 100
}
}
},
"warm": {
"min_age": "2d",
"actions": {
"allocate": {
"number_of_replicas": 0
},
"forcemerge": {
"max_num_segments": 1
},
"set_priority": {
"priority": 50
}
}
},
"cold": {
"min_age": "30d",
"actions": {
"allocate": {
"number_of_replicas": 0
},
"set_priority": {
"priority": 0
}
}
},
"delete": {
"min_age": "90d",
"actions": {
"delete": {}
}
}
}
}
}'
Bu policy ile log verisi şu şekilde yönetilir:
- Hot aşama: Index 30 GB’a ulaşır veya 1 günü geçerse rollover yapılır. Yeni bir index açılır.
- Warm aşama: 2 gün sonra replica kaldırılır, segment’ler birleştirilir. Okuma azalmıştır, replica gerekmez.
- Cold aşama: 30 günlük veriye nadiren erişilir. Düşük öncelikli node’lara taşınır.
- Delete aşama: 90 gün sonra index silinir.
Cluster Sağlığı ve Shard Sorunlarını Tespit Etmek
Shard sorunlarını proaktif olarak izlemek için şu sorguları düzenli çalıştırın:
# Cluster genel sağlık durumu
curl -X GET "localhost:9200/_cluster/health?pretty"
# Unassigned shard'ları listele ve nedenini öğren
curl -X GET "localhost:9200/_cluster/allocation/explain?pretty"
-H 'Content-Type: application/json'
-d '{
"index": "sorunlu-index",
"shard": 0,
"primary": true
}'
# Hot thread analizi (hangi thread ne yapıyor)
curl -X GET "localhost:9200/_nodes/hot_threads"
# Node bazında detaylı istatistikler
curl -X GET "localhost:9200/_nodes/stats/indices,jvm,os?pretty"
Cluster sağlığı “yellow” ise genellikle replica shard’lar atanamamıştır. Bunun en yaygın nedeni:
- Tek node cluster’da replica sayısının 1 olması (replica, primary ile aynı node’a yerleşemez)
- Node sayısından fazla replica tanımlanmış olması
- Disk doluluk oranının %85 eşiğini aşması
Cluster sağlığı “red” ise primary shard’lardan en az biri erişilemiyor demektir. Bu ciddi bir durumdur ve hemen müdahale gerektirir.
Shrink API ile Shard Sayısını Azaltmak
Eğer bir index’in shard sayısı gereğinden fazlaysa ve reindex yapmak istemiyorsanız, Shrink API kullanabilirsiniz:
# Index'i shrink için hazırla (tüm shard'lar aynı node'da olmalı)
curl -X PUT "localhost:9200/eski-index/_settings"
-H 'Content-Type: application/json'
-d '{
"settings": {
"index.routing.allocation.require._name": "hedef-node-adi",
"index.blocks.write": true
}
}'
# Shrink işlemini gerçekleştir (6 shard'dan 3 shard'a)
curl -X POST "localhost:9200/eski-index/_shrink/yeni-index"
-H 'Content-Type: application/json'
-d '{
"settings": {
"index.number_of_shards": 3,
"index.number_of_replicas": 1,
"index.routing.allocation.require._name": null,
"index.blocks.write": null
}
}'
Shrink işlemi için ön koşullar:
- index.blocks.write: true olmalı (yeni yazı kabul edilmemeli)
- Tüm primary shard’lar aynı node’da toplanmış olmalı
- Hedef shard sayısı, kaynak shard sayısının tam böleni olmalı (6’dan 3’e gidebilirsiniz, 4’e gidemezsiniz)
Sonuç
Elasticsearch performans optimizasyonunda shard ve replica ayarları, en temel ve en etkili müdahale noktasıdır. Özetlersek:
- Shard boyutunu 10-50 GB arasında tutmaya çalışın. Bunun dışına çıkmak neredeyse her zaman sorun yaratır.
- Over-sharding’den kaçının. Özellikle küçük index’lerde varsayılan 5 shard değerini körce kullanmayın.
- Index template tanımlayın. Otomatik oluşturulan index’lerin doğru ayarlarla açılmasını garanti altına alın.
- ILM kullanın. Zaman bazlı veriler için lifecycle policy olmadan yönetim kabusu haline gelir.
- Bulk yüklemelerinde geçici optimizasyon uygulayın. Replica’yı kapatmak ve refresh’i devre dışı bırakmak, yükleme hızını dramatik biçimde artırır.
- Cluster sağlığını düzenli izleyin. Unassigned shard’lar, küçük bir ihmal nedeniyle büyük sorunlara dönüşebilir.
Elasticsearch, doğru yapılandırıldığında inanılmaz ölçeklenebilir ve hızlı bir sistem sunar. Yanlış shard ayarlarıyla ise en güçlü donanımı bile boğabilirsiniz. Bu nedenle her yeni index oluşturduğunuzda bir dakika durun ve veri boyutunu, büyüme hızını ve cluster kapasitesini göz önünde bulundurarak bilinçli bir karar verin.
