Yazar | Sun Xuan
Baş Editör | Guo Rui
Kaynak | Beauty of Architecture (ID: beautyArch)
Kafka, tüm dünyada oldukça popüler olan ve özellikle büyük veri projelerinde sıklıkla kullanılan, yüksek verimli dağıtılmış bir yayın-abone mesajlaşma sistemidir. Pek çok büyük verili açık kaynaklı ürünün kaynak kodunu gördüm ve yazarın mükemmel kodlama seviyesi ve üstün mimari tasarım yetenekleri sayesinde Kafka'nın kaynak kodunun en iyi kalitede olduğunu düşünüyorum.
Kafka'nın çekirdek kaynak kodu iki bölüme ayrılmıştır: istemci kaynak kodu ve sunucu kaynak kodu. Müşteri, üreticiler ve tüketiciler olarak bölünmüştür. Şahsen, üreticinin Kafka'nın kaynak kodundaki kaynak kodunun en yüksek teknik içeriğe sahip olduğunu düşünüyorum, bu nedenle bugün Kafka'nın Üreticinin mimari tasarımı, Kafka hızla gelişen bir mesaj sistemidir ve mimarisi de gelişmektedir.Bugün analiz ettiğimiz Kafka versiyonu, Kafka 1.0.0'ın nispeten olgun ve kararlı kaynak kodudur.
Şekil 1 Kafka çekirdek modülleri
Üretici sürecine genel bakış
Önce üreticinin genel işleyiş sürecini tanıtmama izin verin.
Şekil 2 Kafka çalışma modu
ŞEKİL'de gösterildiği gibi:
Adım 1: Bir mesaj ilk olarak bir ProducerRecord nesnesine kapsüllenecektir.
Adım 2: Sonra, bu nesneyi serileştirmemiz gerekiyor, çünkü Kafka'nın mesajının istemciden sunucuya iletilmesi gerekiyor ki bu ağ iletimini de içeriyor, bu yüzden dizinin uygulanması gerekiyor. Kafka, varsayılan bir serileştirme mekanizması sağlar ve ayrıca özel serileştirmeyi destekler (bu tasarım, projenin ölçeklenebilirliğini iyileştirmek için birikimimize de değer).
Adım 3: Mesaj serileştirildikten sonra, mesajın bölümlenmesi ve bölümleme sırasında kümenin meta verilerinin elde edilmesi gerekir. Bölümleme süreci kritiktir, çünkü şu anda mesajımızın Kafka sunucusunun hangi konu ve hangi bölümüne gönderileceğine karar verilmiştir.
Adım 4: Bölünen mesajlar doğrudan sunucuya gönderilmez, bunun yerine üreticinin önbelleğine alınır. Bu önbellekte, birden çok ileti bir toplu iş (toplu iş) içinde kapsüllenir, varsayılan toplu iş boyutu 16K'dır.
Adım 5: Gönderen iş parçacığı başlatıldıktan sonra, önbellekten gönderilebilecek grupları alacaktır.
Adım 6: Gönderen iş parçacığı, sunucuya toplu işler gönderir. Herkesin bu tasarıma dikkat etmesi gerekir.Kafka 0.8'den önce, Kafka üreticisi sunucuya bir veri parçası göndermek için tasarlanmıştı. Sonraki sürüm mimariyi yeniden geliştirdiğinde, bu bir toplu işleme yöntemine değiştirilir ve performans katlanarak iyileştirilir.Bu tasarım birikimimize değer.
Üretici detaylarının derinlemesine analizi
Sonra, üreticimizin nispeten yüksek bir teknik içeriğe sahip olduğu bir yer burası.Önceki genel bakışta, bir mesaj bölümlendikten sonra mesajın bir önbelleğe yerleştirileceğini gördük.Özel ayrıntılara bakalım. Varsayılan önbellek blok boyutu 32M'dir.Bu önbellek bloğunda önemli bir veri yapısı vardır: toplu işler, bu veri yapısı anahtar / değer çiftinin sonucudur, anahtar mesaj konusunun bölümüdür, değer bir kuyruktur ve içinde depolanan içerikler karşılık gelen Bölümlenmiş gruplar için, Gönderen iş parçacığı bu grupları sunucuya gönderir.
Şekil 3 Üretici mimarisi
01 Üreticinin gelişmiş tasarımının özel veri yapısı
Üretici, parti bilgilerini saklamak için grupları kullanır. Herkes olsaydı, toplu bilgileri depolamak için hangi veri yapısını düşünürdünüz?
Kafka'nın buradaki yaklaşımı, bir veri yapısını özelleştirmektir: CopyOnWriteMap. Java'ya aşina olanlar, JUC altında CopyOnWriteArrayList veri yapısı olduğunu bilirler ancak CopyOnWriteMap yoktur.Kafka'nın neden böyle bir veri yapısı tasarladığını size açıklayacağım.
1
Depoladıkları bilgiler anahtar-değer yapısıdır, anahtar bölümdür ve değer, bölümde depolanacak karşılık gelen partidir (birden fazla parti olabilir, bu nedenle kuyruk kullanılır), bu nedenle anahtar-değer verisidir Yapı, dolayısıyla Harita veri yapısı kilitleme için kullanılır.
2
Kafka üreticisi yüksek eşzamanlılık senaryosuyla karşı karşıyadır.Bu veri yapısına çok sayıda mesaj girecektir, bu nedenle bu veri yapısının iş parçacığı açısından güvenli olması gerekir, böylece HashMap gibi veri yapılarını kullanamayız.
3
Bu veri yapısının daha fazla okuma ve daha az yazma senaryosunu desteklemesi gerekir. Daha fazlasını okuyun çünkü her mesaj anahtara göre değer bilgisini okuyacaktır.10 milyon mesaj varsa, batches nesnesi 10 milyon kez okunacaktır. Daha az yazın çünkü, örneğin, üreticimizin bir konuya veri göndermesi gerekiyor. Bu konunun 50 bölüme sahip olduğunu varsayarsak, bu grupların 50 anahtar-değer verisi yazması gerekir (bizim 10 milyon parça verinin yazılması gerekmesine rağmen, bu 10 milyon parça doğrudan yığınlara değil, sıranın yığınlarına yazılır, bu nedenle az önce bahsettiğimiz senaryo için, yığınlara yalnızca 50 parçaya kadar veri yazılması gerekir. Yukarı).
İkinci ve üçüncü senaryolara dayanarak, Kafka'nın iş parçacığı güvenliğini sağlayabilen ve daha az okuma ve yazmayı destekleyen bir Harita veri yapısına ihtiyacı olduğu sonucuna vardık. Ancak Java'da böyle bir veri yoktur.Bu gereksinime yakın olan tek şey CopyOnWriteArrayList'dir, ancak bir Map yapısı değildir, bu nedenle Kafka CopyOnWriteArrayList'i taklit eder ve CopyOnWriteMap'i burada tasarlar. Okuma ve yazmanın ayrılması fikri, iplik güvenliği sorunlarını çözmek ve daha fazla okuma ve daha az yazma desteği sağlamak için benimsenmiştir.
Verimli veri yapısı, üreticinin performansını garanti eder. (CopyOnWriteArrayList'e aşina olmayan öğrenciler Baidu Learning'i deneyebilirler). Burada, Kafka üreticisinin toplu işlere veri ekleyen kaynak kodunu kontrol etmenizi öneririm.Eklenen verinin yüksek performansını sağlamak için üretici çoklu iş parçacığını benimser ve iş parçacığı güvenliği için bölümlü kilitleme gibi birden fazla yöntem kullanır. Kaynak kodu harika.
02 Üreticinin gelişmiş tasarımının bellek havuzu tasarımı
Partilerin gruplar halinde depolandığını az önce gördük. Grubun varsayılan boyutu 16K ve tüm önbelleğin boyutu 32M'dir. Üreticinin, her parti paketlendiğinde bellek için başvurması gerekir. Normalde, bir parti gönderilirse Gelecekte, 16K bellek GC tarafından toplanacak. Ancak bu durumda, FullGC'yi sık sık tetikleyebilir, bu da üreticinin performansını etkiler, bu nedenle önbellekte bir bellek havuzu (genellikle kullandığımız veritabanının bağlantı havuzuna benzer) tasarlanır ve 16K bellek kullanıldıktan sonra , Verileri temizleyin, hafıza havuzuna koyun ve doğrudan bir sonraki partiden alın. Bu, GC'nin sıklığını büyük ölçüde azaltır ve üreticinin kararlılığını ve verimliliğini sağlar (Java'nın GC sorunu bir baş ağrısıdır, bu nedenle bu tasarım da birikimimize değer).
son
Kafka'nın tasarımında pek çok harika yer var ve bugün sizlerle paylaşmak için bazılarını yakaladık. Daha önce Kafka'nın kaynak kodunu gördükten sonra ileride öğretmen olmak ve mimar yetiştirmek istiyorsam Kafka'nın kaynak kodunu öğrencilerle paylaşmam ve Kafka kaynak kodunu öğrenerek sistem mimarisi yeteneğini geliştirmem gerektiğini düşündüm. Herkes Kafka'nın kaynak kodunu inceleyebilirsiniz! !
Ding Ding, App Store'un tepesine sıçradı. Bulut ofis çağı yaklaşıyor mu?
Uzak ofis 4 büyük çukur, çukurlar "ölümcül"!
GitHub TOP listesinde yer almaya devam eden Çinli geliştiriciler iş başında!
Evde çalışan Ali, Tencent ve ByteDance arasındaki farkı keşfedin
Derinlemesine iyi metin! Sina Weibo mimarları, Weibo bulut yerel teknolojisinin düşünce ve uygulamasını analiz ediyor
2020'de blok zinciri ve dağıtılmış defter teknolojisinin 5 ana eğilimi