Elasticsearch Serisi : 02 Mimari Özellikleri, Sharding, Failovering ve Scaling

By Burak Tungut - 10.12.2015 - Kategori DevOps

Herkese selam!

Blogumu takip ediyorsanız bir önceki makalem Elasticsearch Serisi : 01 Ubuntu Server'a Elasticsearch Kurulumu idi. Eğer seriye yeni başlayacaksanız ve hiç elasticsearch kurulumu gerçekleştirmediyseniz bir göz atmanızda fayda var derim.

Bugün ise aşağıda göreceğiniz ve elasticsearch'de bilmemiz gereken terimlere değineceğiz. Son iki maddemiz olan shards ve replicas'lara biraz ayrıcalık tanıyacağız. Çünkü makalenin odak noktası olarak onları belirledim. Sonraki bölümlerde detaylarıyla diğer maddelerede değineceğiz.

  1. Node
  2. Cluster
  3. Index
  4. Type
  5. Mapping
  6. Document
  7. Shard ve Replica

Bazı yabancı kaynakları incelerseniz node'lardan önce cluster'ları incelediklerini görebilirsiniz. Bu gerçekten garibime gidiyor. Neden mi? Aşağıda değindim. Haydi başlayalım.

Node

Elasticsearch node ismi

Bir server üzerine kurduğumuz ve sonraki makalelerimizde göreceğimiz document'larımızı index'leyip, üzerlerinde query'ler çalıştıracağımız tek bir elasticsearch instance'ına verdiğimiz isimdir. Buna örnek olarak bir önceki makalemizde ubuntu server üzerine kurduğumuz elasticsearch instance'ını verebiliriz. Kendileri bir node olurlar. 

Kurduğumuz bir node özellikle müdahele etmediysek random bir isim alır. Elasticsearch geliştiricileri random bir string vermektense Marvel karakterlerinden bir tanesini random seçerek atanmasını sağlamışlardır. Hatta gelin bir önceki makalede kurduğumuz elasticsearch node'unun ismine bir bakalım.

Bunun için /_nodes endpoint'ine HTTP GET request atmamız yeterli olacaktır. Sense yardımıyla bir request atalım ve node'umuza Marvel karakterlerinden atanan ismi görelim.

Beklentim bir Hulk idi fakat ilk defa duyduğum Balthakk ismi ile karşılaştım smiley

Eğer sonraki alt konuda inceleyeceğimiz gibi bir cluster'ımız varsa ve çok fazla node üzerinde çalışıyorsak yönetilebilirlik açısından default isimler yerine bizim vereceğimiz isimleri tercih etmek durumunda kalabiliiz. Bir node'un ismini sadece bir HTTP POST ile sonradan değiştirebiliyoruz. REST API'lar üzerine kurulu olmasının bir faydası daha! 

Dikkatinizi birde resimdeki ilk key'lerden cluster_name'e çekmek isterim. Bu da node'un dahil edileceği cluster ismimiz. Eğer aynı network'de birden fazla cluster'ımızda varsa default cluster ismi yerine yine kendimiz bir cluster ismi vermek durumunda kalabiliriz diyelim ve şimdi cluster ile konumuza devam edelim.

Cluster

IT sektöründeki çoğu terim Türkçe'ye çevrildiklerinde asıl anlamlarını yitirirler. Ama cluster onlardan biri değil. Küme, demet olarak çevrilebilen cluster Tükçe olarakta gayet anlaşılır olabiliyor. Cluster bir veya birden fazla elasticsearch node'unu içerisinde barındıran yapılardır. Fakat bir cluster içerisinde tutacağımız node'lar rasgele document'lar içeren node'lar olamazlar. Kesinlikle ve kesinlikle aynı amaca hizmet etmeye çalışan, index, routing ve schema'ları aynı olan node'lar olmak durumundadır.

Çünkü bu gereksinimin ve cluster'ların amacı gerektiğinde failover yaparak birbirleri yerine geçebilmek ve(ya) toplam yükü paylaşarak distribute edebilmek. Bakın bu terimleri çeviremedim işte laugh Ama failovering ve distributing için bazı örnekleri aşağıda ve sonraki makalelerimizde beraber yine inceliyor olacağız.

Bir cluster kurmak için node'larda yaptığımız gibi kurulumlar ile uğraşmanıza gerek yoktur. Çünkü fiziksel olarak nitelendirebileceğimiz bir olgu değildirler. Bir nevi node'ları gruplandırmak gibi düşünebiliriz. Bazı node'ları A cluster'ına bazılarını B cluster'ına dahil etmek için yapmamız gereken tek şey kurulu olan node'ların cluster_name'lerini değiştirmektir.

Default olarak bu değer elasticsearch olarak atanır. Eğer bir network - domain üzerinde birden fazla cluster'ınız olacaksa mutlaka benzersiz cluster isimleri seçmelisiniz. Birde her bir cluster için bir den fazla ortamınız varsa bunlar içinde benzersiz isimler belirlemeniz gerekir. İlk aklıma gelen örnekleri paylaşmak isterim;

  1. .....-dev
  2. .....-preprod
  3. .....-prod

Biraz geleneksel oldu ama sizlerinde aklına bunların geldiğine eminim smiley

Index

Node ve Cluster'dan sonra biraz daha üst katmanlara çıkalım. Şimdi sırada Index'ler var. Eğer relational database'lerdeki karşılığına bakmak istersek Index'leri bir database (catalog)'a benzetebiliriz. Ya da benzer karakteristik özelliklere sahip document'ları içerisinde bulunduracak bir collection'a da. Bir node içerisinde 0 veya daha fazla Index bulunabilir. İsimleri benzersiz ve lowercase olmak zorundadır. 

Bir index yaratmak için sadece index'in yaratılacağı bir HTTP POST request yapılabileceği gibi, hiç yaratılmamış bir index ve type içerisine document eklenmeye çalışıldığında da yaratılması elasticsearch engine'e bırakılabilir.

Makalemizin başında asıl odaklanacağımız noktaların Shard'lar ve Replica'lar olacağından bahsetmiştik.
Özellikle belirtilmediyse bir index'in default olarak 5 primary shard'ı ve 1 replica shard'ı bulunur. Özellikle belirtilecekse de bir index'in en az 1 primary shard'ı ve en az 0 repliaca shard'ı bulunmak zorundadır.

Type

Index'lerin altında tanımlanabilecek ve içerisinde documant'ları barındıracak birimlerdir. Relational database'lerdeki karlşılığı tablolara / partition'lara denk gelir. Index'lerde olduğu gibi sınırı yoktur ve isimleri lowercase olup kendi aralarında benzersiz olmak zorundadırlar.

Mapping

Index'ler altında tanımlanacak olan Type'ların nasıl field'lara sahip olacağı ve bu field'larda ne gibi analyzing işlemlerinin yapılacağı bilgisini taşırlar. Bunu relational database'lerdeki column type, relation, index vs. tanımlamalarına benzetebiliriz.

Full text search ya da elasticsearch'ün desteklediği diğer özellikler kullanılacaksa hangi alanların hangi analyzer ile tokenize edileceğini mapping'ler ile bildirilir.

Document

Ve sonraki makalelerde en çok kullanacağımız noktaya geldik. Document'lar aslında Index içerisindeki Type'larında içinde barındıracağımız ve üzerlerinde CRUD işlemleri gerçekleştireceğimiz birimlerdir.

Relational database'deki karşılıkları tablo içerisinde tuttuğumuz verilerdir. Index, Type ve Document için hep relational database'lerdeki karşılığı olabilecek noktalardan örnekler vermeye çalıştım. NoSql engine'ler ile ilk defa tanışan okurlarımın daha iyi anlayabilmelerinden başka amacım yok :)

Örneğin kendi blog sitemden örnek göstereyim. Tabi ki üzerinde devasa search query'ler çalıştırmadığım için bir NoSql çözüme ihtiyaç duymadım. Bu blogta örnek gösterebileceğim Blog adında bir database (catalog) olması, içerisinde Blogs, CategoriesComments gibi tabloların bulunması ve her bir tablonun schema-full olup içerisinde verilerin bulunmasıdır.

Eğer bu blog için relational database değilde elasticsearch gibi bir NoSql çözüm kullansaydım bunların karşılığı tamda şöyle olacaktı;
Blog adında bir Index ve içerisinde tanımlanmış Blogs, Categories, Comments adlarında birer schema-less Type (ve mapping'leri) ve her bir Type'ın içerisinde ise her ne kadar schema-less olsada büyük ölçüde benzer field'lara sahip document'lar olacaktı.

Shard ve Replica

Şu alt konuya geldiğimde nasıl bir başlangıç yapmam gerektiğini bir türlü belirleyemedim çünkü bu iki yapının önemini anlatabilecek sözleri tam olarak seçemiyorum. Anlatımı kullanımından daha kolay. Fakat bazı noktalarda değiştirilemeyen yapılar içerdiği için büyük data'lar içerecek olan bir cluster'ımız varsa son derece dikkatli davranmalıyız.

Shard'lar store edilmiş olan document'ların tutulduğu küçük birimlerdir. Her bir shard aslında birer lucene instance'ına tekabül eder. Daha önce bahsettiğimiz gibi bir Index'in kaç adet shard'a sahip olacağını özellikle belirtmediysek bizler için 5 adet shard yaratılır. Peki bu 5 adet shard aynı data'ları mı içerir?

Hayır! Bir index yarattığımızı ve 1000 adet document store ettiğimizi düşünelim. Bu durumda elasticsearch yaratılan 5 shard'a eşit bir şekilde bu document'ları distribute edecektir (dağıtacaktır).

Şimdi de store ettiğimiz bu 1000 adet document'ın bir field'ına göre search yaptığımızı düşünelim. Aradığımız tüm document'ların aynı shard'da store edildiklerinden emin olamayız. Bu nedenle request'i alan elasticsearch engine paralel olacak şekilde tüm shard'lar üzerinde bu searching işlemini gerçekleştirir ve tüm shard'lar cevap verdikten sonra hepsini concat ederek bize sunar. Her bir shard'ın birer lucene instance'ı olmasının faydasını bu noktada görüyoruz. Çünkü aynı node üzerinde dahi birden fazla shard varsa kendi aralarında paralel olarak çalıştırılabilirler.

Birde replica shard'lara göz atalım. Daha önce belirttiğimiz gibi biz özellikle belirtmedikçe her bir Index'in 1 replica shard'ı vardır. Aslında bu 1 adet replica shard anlamına gelmiyor. Bu söz konusu index içerisindeki her bir primary shard için 1 adet replica shard anlamına geliyor. Replica shard'lar primary shard'ların aksine, söz konusu primary shard'ın içerdiği document'ların birebir kopyasını içerir. Bu da kullandığımız mimari için yatayda failovering ve scaling imkanları sağlayacaktır.

Dilerseniz bunu biraz açalım. Yine 1000 adet document'ın 5 primary shard'a bir node üzerinde distribute edildiğini düşünelim. Ardından aynı cluster'a bir başka node daha ekleyelim. Yani aynı network / domain içerisine dahil edilmiş bir sunucu ve içerisinde kurulu elasticsearch engine'i. Bu durumda 1. node'da ki 5 primary shard 2. node ile paylaşılacaktır. 2,5 birine 2,5 birine paylaşması söz konusu olmadığı için 2-3 ya da 3-2 olacak şekilde bir paylaşım söz konusu olacaktır smiley

Şöyle betimleyebiliriz;

1. Node : S1   S2   S3
2. Node : S4   S5

Primary shard'lar için durum böyle. Birde her bir primary shard'ın birer replica shard'ı olduğundan ve bire bir aynı data'yı içerdiklerinden bahsettik. Şimdi konu dışında bir soru sormak isterim size. Bilgisayarımızda 2 adet hard-disk'in olduğunu düşünelim. Siz 1. hard-disk'in yedeğini alıp 1. hard-disk'te tutmak ister misiniz? Bu hiçte tutarlı bir çözüm olmayacaktır. Bu nedenle primary shard'lar node'lar arasında paylaştırılırken, söz konusu replica shard'lar aynı document'ları tuttuğu primary shard ile aynı node üzerinde barındırılmazlar. Yani aşağıdaki gibi bir paylaşım olur;

1. Node : S1   S2   S3   R4   R5
2. Node : S4   S5   R1   R2

Böyle bir mimarimiz mevcut iken herhangi bir node'un down olması halinde ayakta kalmış olan node'da ki replica shard'lar birer primary shard'a dönüşecek ve consistency bozulmadan cluster'a gelen request'ler yine karşılanabilecektir. Pek tabi artık bir node'umuz mevcut olduğu için bu node'u kaybetmememiz gerekir. Elasticsearch'ün sağladığı failover avantajlarından biri bu idi.

Scaling'e az önce biraz değinmiş olduk zaten. Elimizde 1000 adet document ve 5 primary shard var iken bunu tek bir node'da değil, aynı cluster'da farklı bir node ile distribute ettik. Bu da bir machine üzerindeki I/O işlemlerini azaltacak ve primary shard'ların kendi aralarında paralel işletildiği gibi node'larında kendi aralarında paralel işletilmesini sağlayacaktır.

Aynı zamanda bir node üzerindeki primary shard içerisinde (diğer bir değiş ile lucene instance) tutabileceğimiz document sayısı sınırlıdır. Tabi bu sınıra ulaşmak oldukça kolay değil çünkü bu sınır 2,147,483,519 olarak belirtilmiştir. 

Umarım primary shard ve replica shard'lar için verdiğim bu örnek anlaşılır olmuştur. Söylediğim gibi bazen karmaşık bir hal alabiliyorlar. Planladığım başka bir makalede elimizdeki donanımsal kaynak ve barındıracağımız document sayısı / ivmesine göre nasıl bir hesaplama yapmamız gerektiğini anlatmayı planlıyorum.

Bu konu için şimdilik anlatacaklarım bu kadar smiley
Şimdilik esen kalın...

Yorum Bırak

Facebook
Son Yorumlar