Redis’te Master-Slave ve Sentinel Yapıları
Bu yazıda Redis’in en kullanışlı, ilginç bir o kadar da eğlenceli sentinel özelliğinden bahsetmeye çalışacağım. Ama öncesinde master-slave yapısını kavramamız gerekiyor. Teknik kısma geçmeden önce biraz işin hikayesini anlatayım:
Redis bildiğiniz üzere bir NoSql Database. Verileri anahtar-değer ikilisi(key-value pair) biçiminde muhafaza eder ve onlara çok hızlı erişim sağlar. Bu yüzden de cache işlemleri için yoğun olarak kullanılır.
Verilere erişim için bir master-slave(efendi-köle) yapısı da sunar. Slave dediğimiz şey master’ın kopyasıdır. Yani master güncellendikçe o da güncellenir.
Slaveler default olarak read-only’dir. Yani yalnızca verilerin okunabileceği yapıdadır. Read-only özelliği pasife çekilebilir. Bu şekilde yeni kayıtlar eklenebilir. Ama bu kayıtlar sadece slave’e eklenir. Yani slave, master’ı hiçbir şekilde güncelleyemez. Bu şekilde Redis’ten yalnızca veri almasını istediğimiz bir program varsa slave’e yönlendirilerek erişim güvenliğini sağlayabiliriz.
Bir master’a birden fazla slave eklenebilir. Hatta slavelere de slaveler eklenebilir.
Sentinel yapısı ise oldukça kullanışlı ve enteresan bir yapı. Sentineller Redis örneklerini(instance) izlerler. Eğer master göçerse veya bir şekilde hizmet veremez duruma gelirse ve yeterli sayıda sentinel bunu farkederse master’ı masterlıktan azlederler. Ve oy çokluğuyla bir slave’i master yaparlar. Diğer slave’leri de “kral öldü yaşasın yeni kral!” diyerek yeni master’a biat ettirirler.
Uygulama
Bir örnek üzerinden master-slave yapısına inceleyelim. Önce Redis’i indirmemiz gerekiyor. Şuradan bu işlemi gerçekleştirebilirsiniz. Örnekte incelemeyi Windows işletim sistemi üzerinden anlatacağım. İndirme tamamlandığında şöyle bir dosya yapısı göreceksiniz:
Şimdi redis-server.exe’yi çalıştırarak sunucu uygulamayı ayağa kaldırıyoruz ve karşımıza şöyle bir ekran geliyor:
Redis default olarak 6379 portundan yayın yapıyor. Sunucuyu ayağa kaldırdıktan sonra redis-cli.exe’yi çalıştırıyorum. Sonra aşağıdaki basit komutlarla 6 tane değer set edip önce keys komutuyla key’leri sonra get komutuyla her hangi bir key’in değerini görüntülüyorum.
Şimdi elde bir sunucumuz(server) bir de istemcimiz(client) var. Kolaylık açısından Redis’i indirdiğimiz lokasyondaki redis.windows.conf dosyasını kopyalayıp modifiye edebiliriz.
Bu dosyada öncelikle port kısmını “port 6390″ olarak değiştiriyorum. Daha sonra yorum satırı olan slaveof satırını da aşağıdaki gibi master ip ve portu olacak şekilde düzenliyorum.
Localhost’tan yayın yaptığım için ip’yi 127.0.0.1 girdim. Port ise master sunucunun yayın yaptığı port.
Bu yeni oluşan config dosyasını alıp redis-server.exe üzerine sürükleyip bıraktığımda slave sunucu da ayağa kalkıyor.
Daha sonra command prompt’u açıyorum ve Redis’i indirdiğim klasöre gidiyorum. redis-cli.exe -h 127.0.0.1 -p 6390 komutuyla slave istemcimi çalıştırıyorum. (Tahmin edeceğiniz üzere buradaki h ve p harfleri host ve port kelimelerinin baş harfleri) Sonra keys “*” komutunu çalıştırdığımda hiç bir değer set etmediğim halde aşağıdaki key’leri görüyorum. Yani az önce master’da çalışırken eklediğim kayıtları.
Sentineller
Sentinel oluşturuken dikkat etmemiz gereken önemli noktalardan biri sentinellerin sayısı. Konfigürasyonları yaparken sentineller için karar yeter sayısını(quorum) belirliyoruz. Örneğin 3 sentinel oluşturacaksak bu sayıyı 2 olarak belirleyebiliriz. 5 sentinel olacaksa 3 veya 4 yapabiliriz. İlla belirli bir sayı olacak demek yerine mimarinin kurgusuna göre bir sayı belirlemek gerekiyor. Bunun için de örnek senaryoları incelemekte fayda var.
Redis, bize sitesinde oldukça detaylı bir dokümantasyon sunuyor. Ben de bu dokümanlardaki senaryoları sıralayacağım:
M1, M2, M3.. — Masterlar
R1, R2, R3.. — Slaveler(Replicalar)
S1, S2, S3.. — Sentineller
C1, C2, C3.. — Clientlar
Kutu: Farklı bir bilgisayar veya sanal makine
1. Senaryo: 2 sentinelli yapı
Bu senaryoda karar yeter sayımız(quorum) 1.
- Burada M1‘in başına bir şey geldiğinde, 2 sentinel de erişemediği konusunda uzlaştığından aralarından 1 tanesi(S2) bir redis örneğine (R1) erişebildiği için R1 master seviyesine yükseltilir.
- Eğer soldaki kutunun başına bir şey gelirse S1 de duracak ve S2‘nin uzlaşabileceği bir sentinel olmayacağı için sistem tamamen patlayacak.
- Diyelim ki kutular ayakta ama birbirleri arasındaki bağ koptu ve varsayalım ki R1 aşağıdaki gibi master oldu:
Burada başta birbirine simetrik olarak 2 farklı sistem oluşacak ama daha sonra birbirinden alakasız hale gelecek. Bu yüzden Redis bize diyor ki: “En az 3 kutu ve en az 3 sentinelle kurgunuzu oluşturun”
2. Senaryo: 3 kutu ile temel kurulum
Şimdi 3 kutu ile aşağıdaki gibi basit bir kurulum yaptığımızı düşünelim:
- Burada diyelim ki M1 çalışmayı durdurdu. S2 ve S3 aralarında uzlaşarak slavelerden birini master yapacak ve sistem işlemeye devam edecek.
- Peki ya M1‘in olduğu kutuyla bağlantı koparsa?
Bu defa yine bir slave, master yapılır. Ama M1 de yaşadığı için istemci(client — C1) M1‘e yazmaya devam eder. Dolayısıyla buraya yazılan veri tamamen kaybolur. Çünkü aradaki bağlantı tekrar sağlansa bile M1 bir kez azledildiği için yeni master’a biat eder ve hayatını slave olarak sürdürür. Böyle bir durumu engellemek için bir yöntem var:
min-slaves-to-write 1
min-slaves-max-lag 10
Konfigürasyon dosyasına yukarıdaki satırları ekleyince M1, 10 saniye boyunca en az 1 slave kendisinden veri almıyorsa -tebaası kalmadığı için- kendisi istifa edecek. Lakin Redis’in tabiriyle “ there is no free lunch”. Bu ayar bahsettiğimiz senaryoyu çözse bile bir şekilde 2 slave devre dışı kalırsa M1 yine çalışmayı durduracak ve sistem patlayacak.
3. Senaryo: Sentinelleri istemci kutularında konumlandırma
Elimizde Redis için yalnız 2 kutu olduğunu düşünelim. Bu durumda birini master, birini slave yapabiliriz. Sentinelleri de istemci kutularına yerleştirirsek şöyle bir görsel oluşturabiliriz:
- Bu senaryoda sentineller ile istemciler aynı durumdadır. Redis örneğine müşterilerin çoğu ulaşabiliyorsa durum hiç fena değil. M1 ve S1‘e ulaşılamayacak olursa kalanlar R1‘i master olarak belirleyebilir. Gayet güzel.
- Diyelim ki Redis kutuları ile aradaki bağlantı koptu. Bu defa sentineller ayarlanamayacak.
- Yine varsayalım ki C3 ile M1 ayrı eve çıktı. Bu defa kalan sentineller R1’i master yapacak. Paralel yapılar oluşacak. Yani 2. senaryodaki problemi yaşayacağız.
4. Senaryo: 3’ten az istemci ve her yerde sentineller
3. senaryodaki yapı için elimizde 3 istemci yok diyelim. Aşağıdaki gibi ortaya karışık bir yapı kurabiliriz:
Bu, senaryo 3’ten biraz hallice. Ancak burada, sahip olduğumuz dört kutuda dört sentinel çalıştırıyoruz. Master M1 kullanılamaz hale gelirse, diğer üç Sentinel yük devretme işlemini gerçekleştirecektir.
Senaryolar daha da çoğaltılabilir. İşin özü elimizdeki malzeme ve durumlara göre kafa yorup; avantaj ve dezavantajlarını da göz önünde bulundurarak kendimize has bir kurgu oluşturmak.
Demo
Şimdi basit bir örnekle -kişisel bilgisayarda sadece farklı portları kullanarak- olaya göz atalım.
Yukarıda bir master(port 6379) bir de slave(port 6390) oluşturmuştum. Aynı yöntemle 2. bir slave daha oluşturuyorum(port 6391). Sonra hepsinde keys komutunu çalıştırıyorum(En üstteki master’a ait client):
Şimdi sentinel için bir konfigürasyon dosyası oluşturuyorum. Aşağıdaki değerleri yazıp, sentinel1.conf diye kaydediyorum (İsimlerinden anlaşılacağını düşünerek değerlerin detayına girmiyorum):
port 5000
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1
Sonra command prompt ile dosya yoluna gidip aşağıdaki komutu çalıştırıyorum:
Aşağıdaki gibi bir ekran açılıyor:
Portları değiştirerek sentinel2.conf(port 5001) ve sentinel3.conf(port 5002) dosyalarını oluşturuyorum ve aynı şekilde ayağa kaldırıyorum. Şu anda sistemde 1 master, 2 slave ve 3 sentinelimiz var.
Not: Sağlama yapmak için netstat -ab komutuyla kullanılan portları da görebilirsiniz:
Şimdi master uygulamasını erişilmez hale getirelim. Uyutarak -geçici süreliğine- bu işlemi gerçekleştirebilirim. Master’a bağlı redis-cli uygulamasına aşağıdaki komutu giriyorum:
Sonra sentinellerde bazı olaylar meydana geliyor:
Göreceğiniz üzere master’a ulaşamayınca sentineller “fizik boşluk kabul etmez” deyip apar topar oylama yapıyor ve ilk oluşturduğumuz köleyi(port 6390) efendi seçiyorlar.
Örnek üzerinden incelememiz bu kadar. Bu yazıda Redis’in master-slave ve sentinel yapılarını inceledik.