Dağıtık Sistemlere Yeni Başlayanlar İçin Tavsiyeler
(somethingsimilar.com)- Dağıtık sistemlerin temel zorluğu gecikmeden çok kısmi arızadır; tek bir makinede basit olan istisna yönetimi bile birden fazla makinede protokol tasarımının parçası hâline gelir
- Sağlam dağıtık sistemlerde, ancak gerçek birden fazla makinede, veri merkezi ağ koşullarında ve büyük veri kümelerinde ortaya çıkan hatalar bulunduğundan tek makineli sistemlerden daha maliyetlidir
- İşletilebilir bir sistem kurmak için koordinasyonu azaltıp bağımsızlığı artırmak; backpressure, kısmi kullanılabilirlik, metrikler ve yüzdelik dilim göstergelerini temel araçlar olarak kullanmak gerekir
- Özellik bayrakları, ID alanı tasarımı, veri yerelliği ve servis çıkarma; geçiş ve ölçekleme süreçlerinde arıza kapsamını ve koordinasyon maliyetini düşüren pratik tekniklerdir
- CAP teoremi, sistem kurmanın başlangıç noktasından çok bir tasarım eleştiri aracına yakındır; dağıtık sistemlerde teknik sorunlar kadar ekipler ve organizasyonlar arasındaki sosyal koordinasyon da zordur
Dağıtık sistemleri ilk öğrenirken kolayca gözden kaçanlar
- Dağıtık sistem mühendislerinin pek çok dersi, production trafiğinde yaşanan hatalardan ve operasyonel yaralardan gelir; ancak yeni mühendislerin daha doğrudan ve uygulanabilir bir bağlama ihtiyacı vardır
- Fallacies of Distributed Computing ve CAP theorem kendi kendine öğrenmeye yardımcı olur, ancak az deneyimli bir mühendisin hemen harekete geçmesi için soyuttur
- Dağıtık sistemler daha fazla makine ve sermaye gerektirdiğinden, daha fazla ekibin ve büyük organizasyonların işin içine girmesi kolaydır
- Sosyal sorunlar, yazılım geliştiricilerin işinde genellikle en zor kısımdır; dağıtık sistem geliştirmede ise özellikle belirginleşebilir
- Bazen sosyal çözümler teknik çözümlerden daha verimli ve tatmin edici olur; ancak geçmiş, eğitim ve deneyim mühendisleri teknik çözümlere yöneltir
Arızayı ve maliyeti varsayarak tasarlamak
- Dağıtık sistemler sık sık arızalanır ve daha kötüsü kısmen arızalanır
- Tek bir process’te mutex unlock hatasında process’i çökertmek yeterli olabilir; ancak dağıtık mutex’te unlock hatası, lock protokolünün içinde ele alınmalıdır
- “İki makineye de write göndeririz” ya da “başarana kadar tekrar deneriz” yaklaşımı, write’ın bir tarafta başarılı olup diğer tarafta başarısız olduğu durumları yeterince ele almaz
- Switch arızası, GC pause nedeniyle liderin kaybolması, başarılı görünmesine rağmen uzakta başarısız olan socket write’ı, yavaş bir diskin tüm cluster iletişim protokolünü yavaşlatması gibi durumlar oluşur
- Sağlam bir dağıtık çözüm, tek makineli çözümden daha pahalıya mal olur
- Yalnızca birden fazla makinede ortaya çıkan arızalar vardır; VM’ler ve cloud maliyeti düşürür, ama zaten sahip olduğunuz tek bir bilgisayarda tasarlayıp uygulayıp test etmek kadar ucuz değildir
- Paylaşımlı bir makineye sığması zor veri kümesi boyutlarında veya veri merkezi ağ koşullarında ortaya çıkan arızalar için gerçek bir dağıtık ortam gerekir
- Simülasyon yararlıdır, ancak dağıtık sistem hatalarının tamamının yerini tutamaz
- Sağlam açık kaynak dağıtık sistemler, sağlam tek makineli sistemlerden çok daha nadirdir
- Çok sayıda makineyi uzun süre çalıştırmanın maliyeti açık kaynak topluluğu için yüktür
- Hobi geliştiriciler ve amatör meraklılar, açık kaynağı zaten sahip oldukları makineler ve boş zamanlarıyla geliştirdiğinden, birden fazla makineyi ayağa kaldırıp sürdürerek maliyetini ödeyecek geliştirici bulmak zordur
- Şirket mühendisleri bazı boşlukları doldurur, ancak o organizasyonun öncelikleri kullanıcıların organizasyon öncelikleriyle uyuşmayabilir
Koordinasyonu azaltmak ve arızayı absorbe etmek
- Makineler arası koordinasyondan mümkün olduğunca kaçınmak gerekir
- Yatay ölçeklenebilirliğin özü, veriyi makinelerin birbirleriyle iletişim kurup uzlaşma ihtiyacını en aza indirecek kadar bağımsız yerleştirmektir
- İki makinenin herhangi bir konuda uzlaşması gerektiği her durumda servis uygulaması daha zorlaşır
- Bilgi aktarım hızının bir üst sınırı vardır, ağ iletişimi sanılandan daha güvensizdir ve uzlaşmaya dair sezgiler yanlış olabilir
- Two Generals, Byzantine Generals ve Paxos uygulamanın zorluğunu anlamak yardımcı olur
- Bir problem belleğe sığıyorsa, dağıtık sistem mühendisi için genellikle önemsiz bir probleme yakındır
- Veri birkaç pointer ötesinde değil de birkaç switch ötede olduğunda hızlı işlemek daha zordur
- Tek makineli algoritmalar ve uygulamalar bolca vardır; dağıtık sistemler için literatür ve uygulamalar ise çok daha azdır
- “Yavaş” en zor debug edilen problemdir
- Kullanıcı isteğine dahil olan birden fazla sistemden biri veya fazlası yavaş olabilir ya da birden fazla makineden geçen dönüşüm pipeline’ının bir bölümü yavaş olabilir
- Problemin tanımı, kusurun konumu hakkında neredeyse hiç ipucu vermez; normalde bakılan grafiklerde görünmeyen kısmi arızalar saklı olabilir
- Performans düşüşü çok belirgin hâle gelene kadar zaman, para ve araç gibi kaynakları yeterince almak zordur
- Dapper ve Zipkin bu nedenle oluşturuldu
- Sistem genelinde backpressure uygulanmalıdır
- Backpressure, hizmet veren sistemin istekte bulunan sisteme arızayı sinyallemesi ve istekte bulunan sistemin bu arızayı ele alarak hem kendisinin hem de karşı sistemin aşırı yüklenmesini önlemesi yöntemidir
- Aşırı yük veya sistem arızası sırasında kaynak kullanımını sınırlamak, sağlam dağıtık sistemlerin temel yapı taşlarından biridir
- Uygulamalar çoğunlukla kaynaklar sınırlı olduğunda veya arıza oluştuğunda yeni mesajları düşürmek ya da kullanıcıya hata döndürmek şeklindedir; iki durumda da metrikler artırılmalıdır
- Diğer sistem bağlantıları ve istekleri için timeout ve üstel backoff şarttır
- Backpressure yoksa zincirleme arıza veya istenmeyen mesaj kaybı kolayca oluşur
- Kısmi kullanılabilirlik sağlamanın yolları bulunmalıdır
- Kısmi kullanılabilirlik, sistemin bir bölümü arızalansa bile bazı sonuçları döndürebilme yeteneğidir
- Arama sistemleri sonuç kalitesi ile kullanıcıyı bekletme süresi arasında ödünleşim yapar; süre sınırı dolunca yalnızca topladığı sonuçları döndürebilir
- Özel mesajlaşmada, yalnızca bazı kullanıcıların etkilenmesi; tüm kullanıcılar için bazı mesajların kaybolmasından daha iyi olabilir
- Özel mesajlaşma arızasının herkese açık görsel yükleme gibi ilgisiz bir özelliği etkilememesi için arıza alanlarını ne kadar ayıracağınıza karar vermek gerekir
Gözlemlenebilirlik, kapasite ve dağıtımı operasyon aracı yapmak
- Metrikler, production’da sistemin gerçekte ne yaptığını bilmek için vazgeçilmez araçlardır
- Gecikme yüzdelik dilimleri, belirli eylemlere ait artan sayaçlar ve değişim oranı gibi metrikler, sistemin davrandığına inandığınız hâl ile gerçek davranışı arasındaki boşluğu azaltır
-
- gündeki sistem davranışının 15. gündekinden nasıl farklı olduğunu bilmek, başarılı mühendislikle başarısız büyücülüğü ayırır
- Metrikler sorunları ve davranışı anlamak için gereklidir; ancak sırada ne yapılacağını söylemek için yeterli değildir
- Log dosyaları faydalıdır ama kolayca yalan söyleyebilir
- Bazı hata sınıflarına ait loglar dosya alanının büyük bölümünü kaplasa da gerçek istek oranları düşük olabilir
- Başarı loglarının çoğu tekrardır ve diski patlatabilir; mühendisler hangi hata loglarının yararlı olduğunu sık sık yanlış tahmin eder
- Logları, kodu hiç görmemiş birinin okuyacağını varsayarak bırakmak daha iyidir
- Loglarda görülen tuhaflığı metriklerle doğrulamadan abartmak arızayı uzatabilir
- Ortalamadan çok yüzdelik dilimler kullanılmalıdır
- 50th, 99th, 99.9th ve 99.99th yüzdelik dilimleri, çoğu dağıtık sistemde ortalamadan daha doğru ve faydalıdır
- Ortalama, değerlendirilen göstergenin çan eğrisi dağılımı izlediğini varsayar; ancak mühendislerin önemsediği göstergeler arasında bunun geçerli olduğu durum çok azdır
- Dağıtık sistem gecikmesi çan eğrisi dağılımı izlemiyorsa, ortalama gecikme yanlış karar ve yanlış anlayışa yol açar
- Kapasite tahmini becerisi edinmek gerekir
- Bir iş için kaç makine gerektiğini bilmek, uzun ömürlü bir sistem ile 3 ay içinde değiştirilmesi gereken sistemi ayırır
- 2012 sonu itibarıyla tipik bir makinede 24GB bellek bulunduğu, OS için 4–5GB, istek işleme için en az birkaç GB gerektiği ve tweet id’nin 8 bayt olduğu türden kaba hesaplar gerekir
- Jeff Dean’in Numbers Everyone Should Know sunumu beklenti belirlemeye yardımcı olur
- Özellik bayrakları, altyapıyı rollout etme yöntemidir
- Özellik bayrakları yalnızca frontend A/B testleri için değil, altyapı değişimlerinde de güçlü biçimde kullanılır
- “Big cutover” yaklaşımı, geç keşfedilen hatalar yüzünden rollback’e zorlanır; birçok proje bu nedenle başarısız olmuştur
- Tek bir veritabanından yeni depoyu gizleyen bir servise geçerken, yeni servise paralel write gönderimini yavaşça artırabilir, backfill tamamlandıktan sonra read’leri kullanıcı yanıtında kullanmadan test edebilir, eski ve yeni sistem read’lerini karşılaştırdıktan sonra gerçek read’leri kademeli olarak artırabilirsiniz
- Sorun çıkarsa bayrak değerini düşürmek veya hemen 0’a geri almak mümkündür; trafik miktarını ayarlayarak debug ve deney yapılabilir
- Özellik bayrakları, kod içindeki yerel karmaşıklığı küresel basitlik ve dayanıklılıkla takas eden bir ödünleşimdir
- Altyapı ve verinin birden fazla sürümünün istisna değil, normal olduğunu kabul etmek gerekir
Veri modeli ve sınır tasarımı
- ID alanı sistemin şeklini belirler
- Bir veriye ulaşmak için ne kadar çok ID gerekiyorsa, veriyi partition etmek için o kadar fazla seçenek oluşur
- Bir veri için ne kadar az ID gerekiyorsa, sistem çıktısını tüketmek o kadar kolaydır
- Twitter API v1, tweet’leri tek bir 64 bit sayısal ID ile sorguluyor, oluşturuyor ve siliyordu; bu ID başka verilerle ilişkili değildi
- Tweet sayısı arttığında, aynı kullanıcının tweet’lerini aynı makinede saklayarak kullanıcının tweet timeline’ını ve abonelik timeline’ını verimli biçimde oluşturmak mümkündür; ancak public API tüm tweet’leri yalnızca tweet id ile adreslenebilir hâle getirdiği için, hangi user’ın hangi tweet id’ye sahip olduğunu bilen bir lookup servisi gerekir
- Alternatif olarak tweet sorgulamada user id istemek veya tweet id’nin kendisine user id eklemek mümkündür; ancak ikincisinin maliyeti, tweet id’nin artık k-sortable numeric olmamasıdır
- ID yapısı, özel verilerin anonimliğinin kaldırılması, beklenmedik crawling, otomatik artan ID sorunları ve Insecure Direct Object References gibi saldırıları etkileyebilir
- Veri yerelliğinden yararlanmak gerekir
- Veri işleme ve caching’i kalıcı depoya ne kadar yakın tutarsanız, işleme verimliliği o kadar yüksek olur; cache tutarlılığını ve hızını korumak o kadar kolaylaşır
- Ağ, pointer dereference veya
fread(3)’e göre daha fazla arıza ve gecikme barındırır - Yerellik yalnızca mekâna değil, zamana da uygulanır
- Birden fazla kullanıcı neredeyse aynı anda aynı pahalı isteği yaparsa bunlar tek istekte birleştirilebilir; aynı tür veri istekleri zamansal olarak yakın gerçekleşirse daha büyük tek bir istekte gruplanabilir
- Bu yöntem iletişim overhead’ini düşürür ve arıza yönetimini kolaylaştırır
- Cache’lenmiş veriyi kalıcı depoya geri yazmak kötüdür
- Bu kusur özellikle dağıtık sistem deneyimi az kişilerin ilk tasarladığı sistemlerde görülebilir
- “Russian-doll caching”den söz eden uygulamalarda göze çarpan hatalarla karşılaşma olasılığı yüksektir
- Yaygın belirti, kullanıcı bilgilerinin — örneğin screenname, email, hashed password — eski değerlerine geri dönmesidir
- Bilgisayarlar düşündüğünüzden daha fazla iş yapabilir
- 2012 sonundaki hafif bir web sunucusunda bile 6’dan fazla işlemci, 24GB bellek ve çok büyük disk alanı bulunur
- Modern dil runtime’larında nispeten karmaşık CRUD uygulamaları bile tek bir makinede saniyede binlerce request’i birkaç yüz milisaniye içinde işleyebilir
- Çoğu durumda makine başına saniyede birkaç yüz request, operasyonel yetkinlik açısından övünülecek bir sayı değildir
- Uygulamayı profilleyip ölçüme dayalı verimlilik iyileştirmeleri getirerek daha yüksek performans elde etmek zor değildir
- CAP teoremi, sistem kurma yöntemi değil tasarım eleştiri aracı olarak kullanılmalıdır
- CAP teoremi fazla geneldir ve olası çözüm alanı çok geniştir; bu nedenle birinci ilke olarak alınıp çalışan bir sistem türetmeye uygun değildir
- Sistem tasarımında CAP’in alt sistemlere dayattığı kısıtları tekrar tekrar gözden geçirmek daha iyi bir tasarıma ulaşmayı sağlayabilir
- C, A ve P içinde CA seçilemez
- Servis çıkarmak, encapsulation ve deployment avantajları sağlar
- Burada servis, depolama sisteminden daha yüksek seviyede mantık içeren ve genellikle request-response tarzı API’ye sahip dağıtık sistemi ifade eder
- Belirli bir kodun sistemin içinde değil ayrı bir serviste olması hâlinde değiştirmenin daha kolay olup olmayacağını sürekli değerlendirmek gerekir
- Çıkarılmış servisler, kütüphaneler gibi encapsulation sağlarken; değişikliklerin dağıtımını, client sistemlerinin kütüphanesini upgrade etmekten daha hızlı ve kolay hâle getirebilir
- Küçük servislerin kod ve operasyonel bağımlılıkları daha azdır; sıkı sınırlar, kütüphanelerde izin verilen kestirme yolları azaltır
- Birden çok client sistemi olduğunda paylaşılan kütüphane, her client’ın dağıtımını koordine etmeyi gerektirir; veri bozulması dağıtım sırasına göre oluşabiliyorsa bu daha da zorlaşır
- Client sistemlerinin bakımını yapanlar farklıysa, öncelikler uyuşmadığı için upgrade onayı almak üzere sosyal koordinasyon maliyeti de artar
- Tipik kullanım örneği, değişmekte olan depolama katmanını daha kullanışlı ve yüzeyi küçük bir API’ye sahip servisin arkasına gizlemektir
1 yorum
Hacker News yorumları
Yazıda CALM (mantıksal monotonluk olarak tutarlılık) mutlaka ele alınmalıydı. CAP'ten çok daha kolay anlaşılır ve daha temel bir sonuç; az deneyimli kişilerin bile çok sağlam dağıtık sistemler kurmasını sağlar.
İdempotentlik, CRDT, WAL ve Raft'ın hepsi CALM ilkesinin özel durumlarıdır.
https://arxiv.org/pdf/1901.01930
Burada eksik kalan ama genel ilke olarak sevdiğim bir şey var: tam olarak bir kez teslimat imkânsızdır.
En fazla bir kez ya da en az bir kez mümkündür; hangi hata biçimini kabul edeceğinizi seçip ona göre tasarlamanız gerekir.
Bir küme veritabanında bir satırdaki veriyi başka bir satıra taşımak mümkündür ve bu, bir mesajın teslim edilmiş olması şeklinde yorumlanabilir.
Tüm sistem idempotentse ya da dağıtık sistemin tamamı birlikte geri alınabilir tek bir birim olarak ele alınabiliyorsa tam olarak bir kez teslimat elde edilebilir. Yani alanın dışındaki başka sistemler üzerinde yan etki olmamalıdır.
Bunların ikisi de bir tür mantıksal monotonluk kapsamına girer. İdempotentlik kolay fark edilir; işlem özelliği de WAL ve Raft gibi algoritmalar üzerinden monotonluğa dayanır.
Yazıda CALM (mantıksal monotonluk olarak tutarlılık) ele alınmalıydı. CAP'ten çok daha kolay anlaşılır ve daha temel bir sonuçtur.
https://arxiv.org/pdf/1901.01930
An Overview of End-to-End Exactly-Once Processing in Apache Flink (with Apache Kafka, too!) — https://flink.apache.org/2018/02/28/an-overview-of-end-to-en...
Flink's Fault Tolerance Guarantees — https://nightlies.apache.org/flink/flink-docs-release-1.20/d...
“Sorunu belleğe sığdırabiliyorsanız muhtemelen önemsiz bir sorundur” önermesinin bir sonucu olarak, belleğe sığdırılabilen kapsam sandığınızdan çok daha geniştir.
Büyük RAM'in ne olduğunu bildiğimi sanıyordum; ama büyük bulut sağlayıcıları SAP HANA için 12 TB VM sunmaya başlayınca fikrim değişti.
Yazı da bunu “bilgisayarlar sandığınızdan daha fazlasını yapabilir” diye çok kısaca ele alıyor, ama orada yalnızca 24 GB'lık makinelerden söz ediyor. 2012 koşulları olduğu hesaba katılsa bile, o dönemde de bunun 10 katı RAM'e sahip makineler epey vardı.
Birlikte çalıştığım en umut vadeden kişilere bu belgeyi paylaşıyorum.
Lookout'ta çalışırken Jeff Hodges bu denemeyi bir sunum olarak paylaşmış ve sonuna “mühendisliğin politik değilmiş gibi davranmayın” sonucunu eklemişti.
Kodun kendi adına konuştuğunu düşünenler, bir şeyin nasıl inşa edileceğini etkilemek ve gerçek sonuçlar almak açısından önemli bir boyutu kaçırıyor.
10 yıl sonra bile mühendislik liderliği ile sıradan SRE/DevOps'un temel yetkinlikleri saydığım şeylerin kesişimini bu kadar özlü kavrayan çok kişi yok.
Eski tartışmalar:
https://news.ycombinator.com/item?id=5055371
346 points|jcdavis|12 years ago|42 comments
https://news.ycombinator.com/item?id=12245909
386 points|kiyanwang|8 years ago|133 comments
Harika bir liste; pratik ve gerçekçi açıklamaları da iyi. Moda sözcük yok, “microservices” da yok.
Bu tavsiyelerin önemli bir kısmının tek makineli sistemlere de uygulanabileceğini düşünüyorum. Programlar arası IPC ya da tek bir süreç içindeki iş parçacıklarının koordinasyonu gibi, belli ölçüde dağıtık çok sayıda alt bileşen olabilir.
Tek bir makinenin birleşik belleği kavramı da bir ölçüde yanıltıcıdır; yine de donanım “gerçek” dağıtık ortamlardan daha iyi garantiler sağlayabilir.
Yazıda “dağıtık” ile “tek makine”yi karşılaştıran tavsiyelerin önemli bir kısmı, çok iş parçacıklı ile tek iş parçacıklı karşılaştırmasına da oldukça iyi uyar.
Başka bir eksende, bir program yazıp birçok kişinin çalıştırması için dağıttığınızda bu da bir tür “dağıtık” durum olur. Vahşi doğada farklı sürümler bulunur; uyumluluk ve yükseltme sorunlarını önemsemeniz gerekir, bu yüzden yazıda bahsedilen feature flag'ler de ilgilidir.
Dağıtıklık, tek CPU'dan çoklu CPU'ya, sıkı bağlı çoklu bilgisayarlara ve dünyanın dört yanına dağılmış çoklu bilgisayarlara uzanan bir spektruma daha yakındır; arada birçok nokta ve birçok boyut vardır.
Aynı makinede birden fazla sürecin localhost üzerinden iletişim kurması da çok bilinen bir dağıtık sistem örneğidir; gerçekten de birçok kişi dağıtık sistemleri ilk kez orada öğrenir.
Öyle olsaydı hepimiz tüm kodu güzel dağıtık bellekli MPI programları olarak yazıyor olurduk. False sharing de ortadan kalkar, iletişim örüntülerini açıkça ve derinlemesine düşünmek zorunda kalırdık.
Son birkaç yıl içinde bu yazının yazarıyla kısa süre çalışma fırsatım oldu. Jeff, kendisinden bir şeyler öğrendiğim insanlar arasında en içgörülü ve pozitif olanlardan biriydi.
Yaşadığı zorluklar konusunda şaşırtıcı derecede açıktı; mentorluk ve tavsiye için de rahatlıkla erişilebilir biriydi.
“Dağıtık sistemler sık sık arızalandığı için farklıdır” ifadesindeki kilit nokta basit arıza oranı değil, birden çok düğümden oluşan sistemlerdeki arıza oranıdır.
Ayrıca “dağıtık sistem sorunu” yalnızca ağla bağlı birden çok sunucuda ortaya çıkmaz. Birbiriyle ilişkili düğümlerden oluşan bir küme söz konusuysa, mantıksal olarak bağlı disk dosyaları ya da farklı giriş/çıkış aygıtlarının tamponları da benzer sorunlar yaşar.
Bazı eski kurtlar, bu sorunları hafifletirken ortaya çıkan aşırı karmaşıklıkla alay eder ve yazılımı tek bir sunucuda çalıştırmanın çok daha basit olduğundan yakınır.
Gerçekçi bakarsak AS/400 ya da VAXft döneminde bile bu söz pek doğru değildi; daha da karmaşık çok kullanıcılı, çok süreçli Unix dünyası için ise hiç geçerli değildi.
“Sorunu belleğe sığdırabiliyorsanız muhtemelen önemsiz bir sorundur” bazı dağıtık sistem mühendisleri arasında yaygın bir yanılgıdır.
Hiç de önemsiz değildir; yalnızca ele alınması gereken sorunlar tamamlayıcı bir alana kayar.
Bu yanılgı, düzgün optimize edildiğinde tek bir makinede yapılabilecek işleri 100 makinelik bir kümeyle yapma noktasına kolayca götürür.