2 puan yazan GN⁺ 2023-08-12 | 1 yorum | WhatsApp'ta paylaş
  • Tek bir SaaS uygulamasında Postgres darboğazı ağırlaşınca CPU kullanımı %60–80 aralığında kaldı; bir ara %100’e kadar çıkıp kısa süreli bir kesintiye yol açtı
  • Daha büyük bir DB instance’ına geçerek yapılan dikey ölçekleme zaten sınıra dayanmıştı; aynı yöntemle artan yükü daha fazla absorbe etmek zordu
  • Yazma sharding’i ve mikroservisler kapasiteyi ve operasyonel esnekliği artırabilir, ancak yedekleme, izleme, migrasyon, ORM ve ağ topolojisine kadar uzanan karmaşıklık maliyetini sürekli geride bırakır
  • Pratikte 3 ay boyunca ağır sorgular kaldırıldı, Rails kodu optimize edildi, Postgres ayarları yapıldı ve bazı pahalı salt okunur sorgular replika DB’ye ayrıldı
  • Sonuçta haftalık en yüksek DB CPU kullanımı %90’dan %30’a düştü; yeni nesil mimariye geçmeden önce mevcut sistemi daha uzun süre kullanma payı doğdu

Postgres darboğazı ve dikey ölçeklemenin sonu

  • Tek bir SaaS uygulamasının yükü arttıkça Postgres performansı temel darboğaz haline geldi
    • CPU kullanımı %60–80 bandında kalıyordu
    • En az bir kez %100’e fırlayıp kısa süreli bir kesintiye neden oldu
  • Daha önce DB her yoğunlaştığında daha büyük bir instance’a geçerek zaman kazanılıyordu
    • Bu yöntem sayesinde özellik geliştirme gibi başka işlere odaklanılabiliyordu
    • O dönemde zaten en büyük instance kullanıldığı için artık dikey ölçekleme mümkün değildi

Cazip ama pahalı yeni nesil mimari

  • Tartışılan başlıca seçenekler yazma sharding’i ve mikroservislerdi
  • Yazma sharding’i, bağımsız DB kümeleri kurup veriyi bir bölümleme stratejisine göre belirli bir DB’ye yazma yaklaşımıdır
    • Potansiyel olarak kapasiteyi 2–3 basamak artırabilir
  • Mikroservisler, monoliti birden çok servise ayırır ve her servisin kendi veri deposuna sahip olmasını sağlar
    • Her servisin iş yüküne göre veri deposu seçilebilir
  • Her iki yaklaşım da hata toleransı ve operasyonel dayanıklılık açısından seçenekleri genişletir; ancak o anki hedef DB performansını kontrol edilebilir duruma geri getirmekti

Karmaşıklık bir kez devreye girince sürekli maliyet üretir

  • Karmaşıklıktaki artış, yeni yapıyı uygulama maliyetinin ötesinde daha sonra dikkat maliyetine dönüşür
  • DB sharding’i seçilirse bundan sonraki her teknik kararda yeni karmaşıklık da birlikte ele alınmak zorunda kalır
    • Yedekleme
    • İzleme
    • Migrasyon
    • ORM
    • Ağ topolojisi
  • Mikroservisler de benzer bir yük yaratır; ek mimariyi sürdürmek için özellik teslimi gecikebilir ya da bazı özelliklerden vazgeçilebilir

Önce mevcut sistemde boşluk aramak

  • Büyük bir mimari dönüşüm gerekli göründüğünde bile mevcut sistemde çoğu zaman ek kapasite payı kalmıştır
  • İş yükünü ayarlayarak, performans tuning’i yaparak ve yardımcı sistemler ekleyerek aylar, hatta yıllar kazanılabilir
  • Bu seçenekler uygulanabiliyorsa, yeni nesil sistemi sıfırdan kurmadan önce denemeye değer

Gerçekte yapılan optimizasyonlar

  • İlk çalışmada iki mühendis yaklaşık 3 ay boyunca ağırlıklı olarak DB performans sorunlarıyla uğraştı
    • Tek bir sihirli çözüm yoktu
    • Telemetriyle ağır sorgular bulundu
    • Rails codebase’inde sorguların nerede üretildiği belirlendi
    • Sorgular optimize edildi veya kaldırıldı
    • Çeşitli Postgres ayarları tune edildi
  • İkinci çalışmada başka iki mühendis codebase’i değiştirerek bazı pahalı salt okunur sorguların replika DB’de çalışmasını sağladı
    • Web istemcisinin polling’inin tetiklediği en sık SELECT sorguları ana DB’den ayrıldı

Sonuçlar ve operasyon ilkesi

  • İki çalışmanın toplamında DB’nin haftalık en yüksek CPU kullanımı %90’dan %30’a düştü
    • Haftalık en yüksek CPU kullanımı: {l:90,30}
  • CPU tarafında ciddi bir boşluk oluştu ve ana DB’den yük alabilme kapasitesi de arttı
  • Codebase’in birçok bölümüne dokunulması ve birden fazla geliştiricinin birlikte çalışması sayesinde mevcut sisteme dair dağınık bilgi de birikti
  • Karmaşıklık her zaman kötü değildir; bir gün DB mimarisinin temel sınırlarına ulaşmadan önce daha karmaşık bir yapıya geçmek gerekecektir
  • O zamana kadar mevcut sistemi önce sonuna kadar sıkıştırmak, mümkün olduğunca sıkıcı ve basit sistemlerle daha uzun süre çalışmayı sağlar; maliyet ve pratiklik açısından da avantajlıdır

1 yorum

 
GN⁺ 2023-08-12
Hacker News yorumları
  • Veritabanı performans sorunlarına bakınca, yeni projelerle ilgili en hararetli düşüncem şu: uygulamanın sıcak yolunu hiç join kullanmayacak şekilde tasarlamak.
    Depolama ucuz; her şeyi denormalize edip hepsini transaction içinde güncelleyebilirsiniz. Join’leri kaldırınca ne kadar hızlandığı gerçekten şaşırtıcı. Geçici analiz sorguları için veriyi analiz amaçlı başka bir veritabanına replike edebilirsiniz.
    Amazon’un DynamoDB’si konusunda karmaşık duygularım var, ama doğru kullanmak için önce kullanım desenlerini planlayıp şemayı sonra belirlemek gerektiği fikri ilişkisel veritabanlarına da taşınmaya değer. Bugünlerde, analiz amacı taşımıyorsa join’lerin gereksiz olduğunu bile düşünüyorum. Başlıca veritabanları ACID özelliklerine sahip ve depolama akıl almaz derecede ucuz; o yüzden doğrudan denormalize edin.
    Sıcak partition’ları önlemek için integer yerine UUID’ye yakın bir şey kullanmak daha iyi. Her derde deva değil ve dezavantajları da var; ama bir gün çökecek olan integer’ların mükemmel performansı yerine yatay ölçeklenebilir, “her zaman yeterince iyi” performansa alışabilirsiniz.
    Daha da hararetli bir düşüncem, tüm kolonlara indeks koymak; ama o başka bir günün konusu.

    • Açıkçası hiç katılamıyorum. Bir startup kurarken 1–5. yıllarda performansı neredeyse hiç dert etmedik; 6. yılda belirli bir tabloda performans sorunu patlak verdi ve birkaç aylık mühendislik çalışmasıyla optimize ettik.
      Teknik borç açısından, en baştan her şeyi hızlı yapmaya çalışsaydık çok daha pahalıya patlardı. Geliştirme hızımız ciddi biçimde yavaşlar, muhtemelen birkaç kriz anında başarısız olurduk.
      Bunun yerine, gerçek ihtiyacın üzerinde makine maliyeti olarak ayda birkaç bin dolar fazla ödedik; yeterince mühendis işe alamadığımız ve özellik geliştirme fırsat maliyetinin yüksek olduğu bir dönemde birkaç aylık insan gücünden tasarruf ettik. Darboğazın nerede olacağını önceden bilemediğimiz için, her şeyi baştan hızlı yapmak 10–20 kat daha fazla çalışma gerektirirdi. Bazı darboğazlar beklenmedikti.
      Join’ler büyük ölçekte zararlı olabilir, ama çoğu startup’ın en azından başlarda ölçek sorunu yoktur. Denormalizasyon iyi bir optimizasyon olabilir, ancak her değişiklikte tüm kopyaları senkronize etmenin hız maliyetini ödersiniz. Birileri denormalize edilmiş, otorite olmayan bir alanı güncellemeyen bir bug üretir ve kullanıcılara eski veri gösterilir. Genelde join kullanıp daha sonra read-aside cache vb. ile optimize etmek, şemayı eğip bükmekten toplam maliyet açısından daha ucuzdur.
    • Doğru indekslenmiş ve aynı sunucu içinde yapılan join’lerin performansa büyük etkisi olmamalı. “Join’leri kaldırınca çok daha hızlı olur” sözü, join’leri doğru kullanıyorsanız doğru değildir.
      Buna karşılık bir veriyi 1 yere değil 20 yere yazmak performans açısından çok daha yavaştır; sorgular da inanılmaz derecede karmaşık ve bug’a açık hâle gelir. 18 yeri güncelleyip 2 yeri atlamak olur.
      Denormalizasyonun avantajı olarak ucuz depolama gösteriliyor, ama burada depolama en küçük sorun. Asıl sorun çok daha büyüyen bug yüzeyi ve kötü yazma performansı; bu yazma performansı da okuma performansını kolayca kemirebilir.
    • Uygulamaların “yüksek (tall)” olanları ve “geniş (wide)” olanları vardır. Veritabanı tasarımı ve optimizasyonla ilgili tavsiyelerin neredeyse tamamı yüksek uygulamalar içindir.
      Yüksek uygulama temelde tek bir şey yapar; geri kalan her şey o işi destekler. Aklınıza gelen çoğu Big Tech buna girer. Veri modelinde gerçekten önemli olan yalnızca birkaç itici kavram vardır.
      Facebook özünde insanlar, gönderiler ve reklamlardan ibarettir. Netflix kabaca hesaplar ve diziler/şovlardır. Amazon ürünlerinde temel satıcılar, alıcılar ve ürünlerdir; arkada lojistik için birkaç şey daha olabilir.
      Yüksek uygulamaların çok olmasının nedeni kolay olmalarıdır. Genellikle “enterprise” denen geniş uygulamalardan çok daha kolaydırlar. Enterprise yazılımın kötü olmasının nedeni zor olmasıdır; en az keşfedilmiş alan ve devasa fırsat da buradadır. Oracle gibi yerleşik oyuncular burada berbat durumdadır; yüksek uygulama zihniyetiyle girerseniz siz de öyle olursunuz.
      “Asla join kullanma”, “tek tablo merkezli tasarla” gibi tavsiyeler yüksek uygulamalar için anlamlıdır, ama geniş uygulamalar için korkunç tavsiyelerdir. Çok yüksek uygulama şirketlerinin çekirdek yetkinliklerinin dışındaki işleri denemeye kalkıp feci biçimde başarısız olduğunu sık sık görürüz; çünkü bu tavsiyeyi kutsal sayan insanlarla doludurlar.
      Bu tavsiye, zaten başarılı olmuş, kolay işleri yapan ve alçakta asılı meyvelerin hepsini toplamış şirketler içindir. Henüz başarısının kurbanı olmamış yüksek uygulamaların bile performans uğruna veri modelini paramparça etmesine gerek yoktur. Zaten devasa başarıya ulaşıp performansın son damlasını sıkmaya çalışan şirketler ancak böyle dertlere düşer; en az tavsiyeye ihtiyacı olanlar da tam olarak onlardır. “FAANG yapıyor, sen de yapmalısın”, “1 milyar kullanıcın olursa ne yapacaksın?” gibi yüksek uygulama merkezli tavsiyeler, milyarlarca kişiye reklam göstermekten daha ilginç işler yapmak isteyen insanların zihnini kirletir.
    • Son birkaç yılda, büyük tabloların join performansı sorunlarından çok, geliştiricilerin denormalizasyona yaslanması yüzünden doğan acıları gördüm.
      Büyük join’lerde performansı düzeltmenin yolları var: sonradan materialized view’a itmek ya da kolon bazlı depoya ETL etmek gibi. Ama biri subtotal_cents kolonunu Order, Invoice, Payment, NotificationEmail, UserProfileRecentOrders modellerine kopyalayıp 296 yerde referanslanır veya güncellenir hâle getirirse, normal duruma dönmenin yolu uzar.
    • Join’in kendisinin performans darboğazı olduğu durumları neredeyse hiç görmedim. Gözlemlediğim tek bir ilke varsa o da “tabloları fazla büyütmeyin”dir.
      Sorunlar çoğunlukla geçmiş kayıt niteliğindeki tablolarda çıkar. Günlük operasyon için gerekli veri, gerçek tablonun yalnızca çok küçük bir kısmıdır; hangi indeksler olursa olsun, devasa tablolarda yapılan işler kaçınılmaz olarak yavaşlar. Daha fazla indeks eklemenin kendisi de sorun hâline gelir.
      En azından geleneksel ilişkisel veritabanlarında, tüm kolonları indekslemek tek başına yetmez; kullanılabilecek doğru kolon kombinasyonu indekslerini tanımlamak gerekir. DynamoDB farklı olabilir.
  • Elindekileri sonuna kadar sıkıp, bir süre sıktıktan sonra da probleme bakış biçimini değiştirince; şuradan, buradan ve bir de oradan sıkınca birden geriye çok şey kaldığını fark ediyorsun.
    Devasa bir monoliti yaklaşık iki ay optimize ederek, PM’in ve ekibin artık sıkılacak bir şey kalmadığını düşündüğü 2 bin RPS altı durumdan donanım değişimiyle 3200 RPS altına çıkardık; birkaç gün dokunarak 4 bin RPS’ye, biraz daha çabayla 10 bin RPS’ye, yaklaşık bir hafta sonra da 40 bin RPS’ye çıkardık.
    “Bu kadarı yeter, daha ileri gitmeye gerek yok” deniyordu ama epey şeyi değiştirince tek bir makinede 2 milyon RPS’in üzerine sıçradı; bir ay sonra da düşük gecikmeyle 40 milyon RPS’in üzerinde yükü kararlı biçimde işler hale geldi. Hâlâ biraz daha zorlayacak pay var.
    Şu anda çıkarılabilecek kapasitenin %5’ini bile kullanmıyoruz. Yalnızca problemi düşünme biçimini değiştirmek bile bu kadar fark yarattı. Eski sunucudan yeni sunucuya geçmek tek başına 1800 RPS’den 3000 RPS’nin biraz üstüne çıkarmaktan ibaretti. Donanım eklemek temel sorunu düzeltmedi; karmaşıklık eklemek de sorunu sadece erteledi. Problemi düşünme biçimini değiştirince problemin kendisi ve yanıtı değişti.

    • Monolitin bu kadar performans çıkarılabilecek kadar neyi bu kadar berbat yaptığını gerçekten merak ediyorum. Sorgular mı berbattı, sorgu sayısı mı çok fazlaydı, hiç cache yok muydu, eşzamanlı yapılabilecek işleri senkron mu yapıyordu, merak ediyorum.
    • Bu isteklerin içeriği veya protokolü neydi; istek ve yanıtların ortalama payload boyutu yaklaşık ne kadardı, paylaşabilir misiniz merak ediyorum.
  • “Monoliti birbiriyle bağlantılı birden çok servise bölmek ve her servisin kendi koşullarına göre ölçeklenebilir kendi veri deposuna sahip olmasını sağlamak” sözüne ek olarak: Bu noktada mümkün olan tüm microservice’leri ayırmak gerekmez. “Hangi ayrım en büyük etkiyi yaratır?” diye sormak yeterlidir.
    Benim durumumda Mongo’daki bazı zaman serisi verilerini Cassandra’ya ayırdım. Cassandra’nın tablo yapısı çok daha uygundu. Bu veri kümesinin iyi tanımlanmış bir şeması vardı ve Cassandra veriyi çok daha verimli paketleyebiliyordu. O bölümde JSON belgelerinin esnekliğine ihtiyaç yoktu.
    Bu veri, tüm verinin büyük kısmını oluşturduğu için sonrasında Mongo oldukça tatmin edici bir duruma geldi. Gerekli ayrım yalnızca bir taneydi. Teknik olarak öncesi de sonrası da monolitti; sadece aynı servis iki veritabanına yazmaya başlamıştı.
    İronik biçimde, daha sonra masa başı mimar tipinde biri tüm verileri JSON belge deposunda birleştirmek istedi ve “Bu yolu zaten denedik, sonunun nereye vardığını biliyoruz” minvalinde tartışmalar birkaç kez yaşandı.

    • Microservice fikrinin fazlasıyla bariz bir “çözüm” gibi ortaya atılması ilginç. Öyle değil.
      Dikey ölçekleme bariz ilk çözüm olmalı. Birçok kişinin kaçırdığı nokta bu; yazıda da kısmen ele alınıyor ama dikey ölçekleme, veritabanı tutarlılığını bozmayan yatay ölçeklemeye yakındır.
      Sıkılabilecek çok pay vardır ve performans sorunu çıktı diye join’leri veya veri doğrulamayı göz ardı etmek gibi anti-pattern’leri kolayca ortaya atmayı gerektiren durumlar nadirdir.
    • Yazıda da bir anlamda ayrıştırma yapılmış. Çünkü belirli ağır SELECT sorguları replikaya yönlendirilmiş.
    • İlginçtir, ben sık sık bunun tersi problemi yaşıyorum. Görece kısa ömürlü ve sık güncellenen veriler için Cassandra’nın neden uygun olmadığını sürekli açıklamam gerekiyor. Sebep tombstone’lar.
    • Tek bir sunucunun iki veri deposundan okuyabilmesi de önemli. Kardeş yorumda bahsedilen okuma replikası gibi, aynı süreç içinde Postgres ve Redis’i birlikte okumayı engelleyen bir şey yok.
  • Geliştiriciler EXPLAIN/ANALYZE sonuçlarını okuyup doğru indeksleme ve sorgu optimizasyonu yapmayı bilirse, sayısız aşırı tasarım kararından kaçınılabilir.
    Sorguları kaydedip, çok sık çalıştırılanları veya çalışma süresi uzun olanları filtreleyip, sık çalışanları cache’leyip, ağır olanları optimize etmek yeterli. Bunu sistematik yaparsanız sistem daha sağlıklı hale gelir.
    Benim deneyimime göre büyük fayda sağlayan şeyler APM, yavaş sorgu logları, veritabanı okuma/yazma replikaları, partitioning ve sharding.

    • explain çıktısını okumak başlı başına oldukça büyük bir iş olabilir. Veritabanları tamamen ayrı bir dünya; özellikle de doğrudan SQL’i neredeyse hiç kullanmıyorsanız.
      https://explainmysql.com gibi araçlar gerçekte neyin optimize edilmesi gerektiğini daha net gösterir; bu da veritabanını yapılandıracak kadar bilgisi olan ama içeride nasıl kullanıldığını anlayacak düzeyde olmayan geliştiriciler için daha kolay bir sistem sağlar.
      Muhtemelen birileri, şema ve logları verince sihirli biçimde iyileştirme yapacak SQL’i çalıştıran bir yapay zeka sistemi zaten geliştiriyordur. Güvenir miyim bilmiyorum ama birçok şirket özel bir DBA işe almaktansa böyle bir şeyi kullanmak isteyecektir.
    • SQL yürütme planlarını anlamak için iyi kaynaklar var mı merak ediyorum. Mevcut projede MS SQL Server sorgu performansı sorunlarını çok yaşıyoruz.
      Her sorguda her zaman indeks hint’i belirtmek gerekir mi bilmiyorum. İndeks mevcut olmasına rağmen sorgunun o indeksi kullanmıyor gibi göründüğü zamanlar oluyor. SQL yürütme planlarını kullanırsam bu sorunu daha iyi anlayabileceğimi düşünüyorum.
    • Kaç tane “yeni nesil mimari” oturumu gördüğümü sayamıyorum; çoğunun yerini mevcut implementasyonun due diligence’ı alabilirdi.
      Kötü kodu yeni bir mimariyle düzeltemezsiniz. Sorunu yalnızca bir süreliğine ertelersiniz.
  • Sevdiğim sözlerden biri aklıma geldi: “İstediğin ya da ileride sahip olmak isteyeceğin orduyla değil, şu anda elindeki orduyla savaşa girersin.”
    Bu sözün Donald Rumsfeld’den çıktığı gerçeğini görmezden gelmek isteyebilirsiniz. Yine de “unknown unknowns” gibi harika ifadeleri de var.
    Bir ekipte çalışırken bu sözü sık sık hatırlarım. Herkes tamamen hemfikir değildir ya da aynı anlayışa ve ortak hedefe sahip değildir. Birileri verimsiz ya da benim tercih etmeyeceğim bir şekilde çalışıyor olabilir. Ama bir ekibin olması, hiç ekip olmamasından daha iyi olduğu için, elindeki ekiple hedefe ulaşmanın en iyi yolunu bulman gerekir.
    Sistemlere de iyi uygulanır.

    • Rumsfeld’in epey iyi alıntısı var. Çoğu, Irak Savaşı’nın nasıl bu kadar berbat hale geldiğini açıklama bağlamında ortaya çıkmıştı; o durum da, yalnızca alıntılarına bakınca onun sağlayabilecekmiş gibi göründüğü liderliğe tam da en çok ihtiyaç duyulan durumdu.
    • Rumsfeld adını her duyduğumda, 10 dakikadan uzun süre boyunca kertenkele olmadığını inkâr etmeyi reddettiği sahne aklıma geliyor.
      https://www.youtube.com/watch?v=XH_34tqxAjA
    • “Hiçbir savaş planı, düşmanla temas ettikten sonra hayatta kalmaz.”
      https://www.google.com/search?q=no+battle+plan+survives
    • Mattis’in “Düşmanın da bir oyu vardır” sözü de gerçekliği hatırlatan iyi bir ifade. İnsanlar çok öfkeleniyor ama güvenlik, gizlilik, DRM gibi bağlamlarda yararlı.
    • Steven Pressfield’in benzer cümlesini de seviyorum: “Sporcu, acısız uyandığı bir günün asla gelmeyeceğini bilir. Sakatken oynamak zorundadır.”
      Bu, sistemlerden çok kendimize daha iyi uygulanır.
  • Deneyimlerime göre, ORM üzerine kurulmuş web uygulamalarında veritabanı yükü sorun olduğunda sorgu optimizasyonuyla toplanabilecek inanılmaz miktarda alçakta asılı meyve oluyor.
    “N+1 problemi var mı?” gibi temel konuların ötesinde, ORM bazen en uygun sorguyu üretemiyor. Karmaşık bir üretim web uygulamasını ORM olmadan yapmak istemem ama zaman zaman ORM’den çıkabilmek gerekiyor.
    Üretimde gerçekten çalışan ve en çok kaynağı tüketen sorguları profillemek gerekir. O sorguya bakıp hedef tabloların yapısını anlamak gerekir. ORM join kullanıyor olabilir ama gerçekte alt sorgu gerekebilir; tersi de olabilir. Sonuçların bir kısmını önceden toplulaştırmak ya da karmaşık join’lerde WHERE koşullarını ayarlamak gerekebilir.
    Yarı sık çalışan, ORM tarafından üretilmiş bir sorgunun veritabanını öldürdüğünü ve çalışması 20 saniyeden fazla sürerken birkaç küçük düzeltmeyle 1 saniyenin altına indiğini de gördüm.

    • Şu anda Python ORM’i SQLAlchemy ile çalışıyorum; INSERT’te RETURNING kullandırmak önemsiz bir iş değil. Sezgisel olmayan expire_on_commit=False seçeneğini ayarlamak gerekiyor.
      Bu seçenek de RETURNING kullanımını garanti etmiyor; veritabanı sürücüsü ve veritabanı destekliyorsa ve ORM de o sürücü/veritabanı kombinasyonunda destekliyorsa kullanacak şekilde tasarlanmış. Üretilen SQL loglarda görünüyor ama bunu gerçekten denetleyecek bir API yok; kendi loglarınızı yakalayıp kazımazsanız test süitinde RETURNING kullanımını zorunlu kılmanın yolu yok. Neyse ki Pytest framework’ü içinde bu oldukça kolay.
      ORM’leri seviyorum ama böyle şeyler birden çok katmanda can sıkıcı derecede karmaşık. SQLAlchemy’nin devasa bir kütüphane olduğunu, her şeyin kolay olamayacağını da anlıyorum. Yine de bu örnek, ORM kullanmanın ödünleşimini iyi gösteriyor.
      Core’da insert()’in kendisini kullanırsanız istediğiniz gibi olduğunu biliyorum. Burada ORM nesnesini AsyncSession’a .add() etme durumundan bahsediyorum.
    • ORM’in büyük sorunu, nesne yönelimliliğin çoğu alanda yazılımı ya da veriyi organize etmek için iyi bir yöntem olmamasında yatıyor.
      Çoğu iş mantığı, OOP yerine ilişkisel cebirin dili ve birkaç uzantıyla daha iyi ifade edilir.
  • “Karmaşıklık artışının gerçek maliyeti, ve çoğu zaman çok daha büyük maliyeti, dikkattir” sözü aynı zamanda bilişsel yük anlamına da geliyor.
    Hâlâ kesinti yaşanan ama kimsenin bütünün nasıl çalıştığını bilmediği mikroservis sistemlerinde çalışmaktan yoruldum. Çoğu gerçekte dağıtık monolit; değişiklikler birden fazla servise yayılıyor ve sırayla dağıtılmaları gerekiyor. Verinin replike edilmesi, işlerin senkronize edilmesi ve durumun paylaşılması gerekiyor.
    https://www.youtube.com/watch?v=y8OnoxKotPQ

    • “Kimsenin bütünün nasıl çalıştığını bilmediği” mikroservisler çok yaygın bir mimari kokudur. Asıl fikir, kimsenin bütünü bilememesi ve bilmek zorunda olmaması gerektiğidir.
      Ama sistemi onarmak ya da değiştirmek için birinin bütünü bilmesi gerekiyorsa, bu tek sorumluluk ya da API’ler üzerinden doğru soyutlama gibi kuralların ihlal edildiğine dair güçlü bir işarettir. Yine de deneyimlerime göre çok yaygın. N mikroservisten oluşan bir pipeline’ı debug etmek için çoğu zaman N servisin tamamını yerelde çalıştırıp build etmek gerekir.
      Kesin konuşmak gerekirse bu, monolite ağ bölünmeleri ve sınırsız build/dağıtım değişkenliği eklenmiş halidir. Sonuçta bunun, herhangi bir insan programcının kapasitesini aşan aşırı zor bir çalışma ortamı olduğunu düşünüyorum.
  • Bu yazıyı beğendim. Son birkaç aydır yöneticime aynı mesajı iletmeye çalışıyordum ama pek başarılı olamadım.
    Aşırı yüklenmiş Redshift cluster’ımız birkaç kez çöktü; zaten RA3 node’larıyla maksimuma çıkarılmış durumda, bu yüzden şimdi “yeni nesil altyapı”ya büyük bir migrasyon başlatmak üzereyiz. Burada kastedilen yeni nesil altyapı, CDK ile yönetilen üç Redshift cluster’ı.
    Yeni altyapı mevcut yapılandırmadan çok daha karmaşık ve herkesin beklediği gümüş kurşun olup olmayacağından emin değilim.

  • Sıkıcı çözüm bu. Yaşam ve beden güvenliğiyle doğrudan ilişkili, aşırı kritik sistemler inşa etmiyorsanız varsayılan cevap bu olmalı. Toplam sahip olma maliyeti kesinlikle çok daha düşük olur.
    Büyük yedekli sistemleri işletmek için kaynak yoksa, yedekli sistemin eklediği karmaşıklığın bizzat sorun haline geldiğini çok sık gördüm. Basitliğe odaklanmak daha iyi.
    Karmaşıklığı desteklemek için çok daha fazla insan eklemek gerekiyorsa ama para ve risk değerlendirmesi açısından buna gerek yoksa, daha basit olan taraf çok daha iyidir. Sonunda ilerlemek için devasa bir projenin gerekli hale geldiği vakaları görmedim değil; ama bazen bunun bile o noktaya kadar karmaşıklığı sürekli taşımış olmanın toplamından daha küçük olduğunu düşünüyorum. Bu, ne inşa ettiğinize çok bağlı.

  • Sistemlerde performans optimizasyonu bulup kalan performansı son damlasına kadar çıkaran çözümler gerçekten keyif verici
    Richard L. Sites’ın Understanding_Software_Dynamics kitabı aklıma geliyor. Bu kitap, gecikme süresi sorunlarını nasıl ölçeceğinizi ve düzelteceğinizi, ayrıca büyük ölçekte gecikmeyi azaltmanın ne kadar büyük tasarruflar sağlayabileceğini öğretiyor
    Bu tür sorunları ölçmek ve akıl yürütmek zor, ama çözümler çoğu zaman basit oluyor. Örneğin 9. sayfada “[a] simple change paid for 10 years of my salary.” diyor
    Bir gün ben de bu kadar etkili bir optimizasyon yapmak isterim

    • Google’da böyle bir şeyi en az bir kez yaptım. Google muazzam miktarda makine kaynağı kullanıyor ve harika performans araçlarına da sahip; bu yüzden verimli bir ortam
      https://research.google/pubs/pub36575/
      Ancak etrafta çok sayıda zeki insan da olduğundan, büyük bir fırsat bulduysanız genellikle başkalarının neden atlamadığına dair bir sebep vardır. Teknik bir sebep de olabilir, organizasyonel bir sebep de
      İkincisine örnek olarak, Google genelde kaynak baskısı olmadığı sürece bu tür işleri çok büyük ölçüde ödüllendirmez. Bir optimizasyon sayesinde ekip arkadaşlarımdan yaklaşık 100 dolarlık bir bonus almış olabilirim; ama %10 komisyon, terfi ya da 10 yıl işe gelmeden maaş alma hakkı gibi bir şey kesinlikle değildi. Genel olarak şirketler, mühendislerin maliyet düşürmekten çok gelir büyümesi üzerinde çalışmasını tercih eder. Bu politikanın doğru olup olmadığı benim maaş seviyemin üstünde bir konu
    • Nihai çözümde içime sinmeyen nokta, sorguyu ancak instance’ı mümkün olan en büyük ayara yükselttikten sonra optimize etmiş olmaları
      Artık yönetim konsolunda birkaç tıklamayla ayarı daha da yükseltemez hale gelmişlerdi; bu yüzden kapasite sorununu çözmek için gerçekten kafa yormaları gerekmiş gibi görünüyor. Kodun belirli bir bölümünü daha erken optimize etselerdi, belki de o kadar büyük bir instance ayarına en baştan ihtiyaç kalmayacaktı