
Benim adım Yuri ve Citymobil'de sistem yönetimi ekibinin başıyım. Bugün, dosya sistemleri için ince provizyonlama teknolojisiyle çalışma deneyimimi paylaşacağım. Linux Bunun bir şirketin CI/CD süreçlerinde nasıl uygulanabileceğini açıklayacağım. Üretime teslim edilen kodu otomatik olarak test etmek için, üretim sürümüne mümkün olduğunca yakın MySQL veritabanının okuma-yazma kopyalarına ihtiyaç duyduğumuz bir durumu inceleyeceğiz.
Giriş: Neden kötü tavsiye veriyorsunuz?
Mantıklı bir soru çünkü veritabanı şemalarını test ortamlarına geçirmek için kanıtlanmış mekanizmalar var. Neden parçalanmamış ana DBMS'yi bu tür birimlere genişletesiniz ki? Ve test için tüm verilere ihtiyaç yoktur. Açıklamaya çalışacağım.
Yaklaşık bir yıl önce, taksi toplayıcımızın aktif büyümesinin arka planında (2018'de tamamlanan yolculuklar yaklaşık 15 kat arttı), veri hacmi, sunuculardaki yük ve kullanıma sunma sıklığı arttı. Kendimizi şu durumda bulduk:
- Ana MySQL veritabanı toplamda 1000 TB'a ulaşan yaklaşık 2,5 tabloya ulaştı ve büyümeye devam etti.
- Hızla parçalanıp üssü yok etmenin bir yolu yoktu. Eski yaklaşım "Veritabanına ne istediğimi ve nasıl istediğimi yazıyorum", bir dizi JOIN ve dahili tablo bağımlılığı buna izin vermiyordu.
- Veritabanı şemasını test ortamlarına geçirmek için herhangi bir mekanizma yoktu.
- Dağıtım sırasında kodun otomatik testi yapılmadı.
Son sorunu olabildiğince çabuk çözmek istedim. Postacı testleri ana PHP monolitini test etmek için zaten yazılmıştı ancak güncel bir veritabanı yoktu. Aynı zamanda, geceleri bir kopya oluşturup, onu bir ana kopya haline getirip gün içinde parçalara ayıramadık: veri ve veritabanı şeması da dahil olmak üzere çok sayıda kullanıma sunma ve değişiklik, gün ortasında stant kullanılamaz hale geldi. Sunumları yalnızca bir iş günüyle sınırlamak etkisiz olacaktır.
Yine de görev tamamlandı: İlk çalışma standını iki hafta içinde teslim aldık. Geçtiğimiz yıl içerisinde birçok değişikliğe uğradı ve kullanılmaya devam ediyor.
Daha sonra çözümümüzün geliştirilmesinin tüm adımlarını ve aşamalarını ayrıntılı olarak anlatacağım. Bu yöntemin var olma hakkını hak ettiğini göreceksiniz.
"İnce artıklık" nedir?
Bu, gerekli kaynağın mevcut olandan daha fazlasını tahsis etmenize olanak tanıyan bir donanım veya yazılım teknolojisidir (başka bir adı seyrek hacimlerdir). Bu durumda, tahsis edilen hacmin tam yeterli (ihtiyaç duyulan kadar) ve tam zamanında (gerekli süre için) kriterlerini karşılaması gerekir. Temel olarak, çeşitli depolama sistemlerinde, gerçekte mevcut olanları aşan gerekli hacimlerde disk alanı sağlamak için ince rezervasyon kullanılır. Teknoloji, LVM2, ZFS, BTRFS gibi çeşitli dosya sistemleri tarafından desteklenir. Sanallaştırma hipervizörlerinde yaygın olarak kullanılır. İnce yedekleme, ana bölümün anlık görüntülerinden, bu bölümün ihtiyaç duyduğumuz kadar çok kopyasını (MySQL DBMS'nin veri dizini) içeren verileri hızlı bir şekilde oluşturmamıza olanak sağladı.
İlk stand, İnce LVM teknolojisi
Bu bölüm aynı zamanda “Büyük hacimli verilerin anlık görüntülerinin en hızlı şekilde nasıl elde edileceği” olarak da adlandırılabilir. , dosya sisteminin ve MySQL DBMS'nin kararlılığını uygunsuz seviyelere düşürüyor."
Ana işletim sistemi bölümlerini oluşturmak için zaten LVM'yi kullandığımız için onunla başlamaya karar verdik. Başlangıç olarak, ayrı bir fiziksel makineye ihtiyacımız vardı; ana MySQL veritabanımızın bir kopyası; bu makinede istek üzerine kopyanın anlık görüntüsünü oluşturabilir ve onu ayrı bir MySQL örneğinin yanına yükseltebiliriz. Test sırasında bu örnekte değişiklik işlemlerinin kullanılmasına izin verdik ve testler tamamlandıktan sonra onu güvenli bir şekilde sildik. Sunucu yapılandırması şu şekildeydi:
- 2 x Intel Gümüş 4114 (10x2,2 GHz HT)
- 8 x 32 GB DDR4
- RAID-8'da Adaptec RAID denetleyicisinde 1920 x 10 GB Intel SSD
RAID denetleyicisi ile RAID MD yazılımı arasında seçim yapma konusunda ayrı bir makale yazabilirsiniz. Seçimimizin iki faktörden etkilendiğini söyleyeyim:
- Sorunun formüle edildiği dönemde tüm DBMS'leri RAID denetleyicilere yükledik, dolayısıyla bunun tarihsel olarak gerçekleştiğini söyleyebiliriz.
- Sentetik dosya sistemi testleri ile çeşitli MySQL işlemleriyle yapılan testler arasındaki performans farkı minimum düzeydeydi.
Ortaya çıkan RAID-10'u böldük: tüm birim için (yaklaşık 6,7 GB ek yük ile) tek bir Birim Grubu (VG) oluşturduk ve 50 GB'lik bir sistem için mantıksal bir bölüm (Mantıksal Birim, LV) oluşturduk. Normal durumda alanın geri kalanını MySQL bölümü olarak tanımlarız. Ancak ince bir yedeklemeye ihtiyacımız vardı, bu yüzden önce havuz adı verilen bir havuz oluşturduk ve bunun içinde /var/lib/mysql için 3,5 TB'lik bir bölüm oluşturduk (tahmini veritabanı hacimlerine göre):
lvcreate -l 100%FREE -T vga/thin
lvcreate -V 3.5T -T vga/thin -n mysqlBölümü ext4'te formatladık, monte ettik, bir kopyasını kaydettik ve orijinal standı aldık. Daha sonra, anlık görüntüler oluşturması, belirli bir bağlantı noktasında bir MySQL veritabanı örneğini yükseltmesi ve oluşturulan örneği silmesi gereken bir API biçiminde bir bağlama yaptık. Bu yalnızca sistem çağrılarını kullandığından, komut dosyası dili olarak normal bash'ı seçtik ve HTTP → bash API'sini bağlamak için açık kaynaklı bir çözüm kullandık. , Go'da yazılmıştır.
Bir gün bash betiklerimizi açık kaynak olarak yayınlayacağız, ancak şimdilik sadece ana algoritmayı anlatacağım:
Ana anlık görüntü anlık görüntüsünü oluşturma:
- Ana kopya durduruluyor.
- Ana anlık görüntü ile işlemlere bir blok koyduk.
- Yeni bir anlık görüntü snapmain'i oluşturun.
- MySQL'i başlatın ve kilidi kaldırın.
Snapmain'den isteğe bağlı bir bağlantı noktasında veritabanı oluşturma:
- Belirli bir veritabanı örneğine (port) kilit koyuyoruz.
- Ana anlık görüntünün oluşturulmasının engellenip engellenmediğini kontrol ediyoruz. Eğer oradaysa, bekleyip her 5 saniyede bir yeniden kontrol ediyoruz.
- Örneğin eski bir LV bölümünün olup olmadığını kontrol ediyoruz.
3.1 Varsa, MySQL örneğini durdurmak ve LV bölümünü silmek için kill -9'u kullanın. - Snapmain'den yeni bir örnek oluşturuyoruz.
- Bu örnek için dizinleri hazırlayıp mount ediyoruz.
- Slave'in (dosyaların) niteliklerini kaldırıyoruz ve MySQL örneğini başlatıyoruz.
- Onu usta yapalım.
- Engellemeyi kaldırıyoruz.
Rastgele bir bağlantı noktasındaki bir veritabanını kaldırmak:
- Belirli bir veritabanı örneğine (port) kilit koyuyoruz.
- Kill -9 kullanarak MySQL örneğini sonlandırın.
- Dizinleri kaldıralım.
- LV bölümünü silip kilidi kaldırıyoruz.
Yeni bir veritabanı örneğinin bölümlerini klonlamaya yönelik örnek komutlar:
lvcreate -n stage_3307 -s vga/snapmain
lvchange -ay -K vga/stage_3307
mount -o noatime,nodiratime,data=writeback /dev/mapper/vga-stage_3307 /mnt/stage_3307Şimdi size ince yedeklilik kullanırken karşılaştığımız temel sorunu anlatacağım. SSD sürücülerin performansına takılıp kaldık. Bu, Thin LVM'nin özellikleri nedeniyle gerçekleşti: Temel olarak, varsayılan boyutu 4 MB olan düşük seviyeli parçalarla cihaz düzeyinde çalışır. Neye benziyordu:
- /var/lib/mysql ana bölümünden bir anlık görüntü oluşturun.
- Master'a yetişmek için replikasyona başlıyoruz.
- Çoğaltma tablolarındaki herhangi bir değişiklik, eski, değişmemiş veri yığınlarının anlık görüntü bölümünde depolanmasına zorlar.
- Yükseltilmiş bir test örneğinde yapılan herhangi bir değişiklik, eski, değiştirilmemiş veri parçalarının söz konusu örneğin klonlanmış bir anlık görüntü bölümünde depolanmasına neden olur.
- Cihazda %100 G/Ç işlemi yükü, tüm işlemlerde yavaşlama ve kopyada kademeli bir gecikmeyle karşılaşıyoruz.
- Çalışma gününün sonunda birkaç saat geride olan bir standla karşılaşıyoruz.
Daha aklı başında bir sonuç elde etmek için bununla nasıl başa çıktık (ana noktalar):
RAID denetleyicisi:
- Tüm önbellekleme türleri varsayılan olarak devre dışıdır.
- Geri yazmayı ayarlayın (veriler arabelleğe girdiğinde, diske gerçek kaydetme işlemi gerçekleştirilmeden önce yazma işlemi tamamlanır).
Dosya sistemi:
- /var/lib/mysql bağlama noktasında şunu yazdık: noatime,nodiratime,veri=geri yazma
- Tune4fs kullanılarak ext2 günlüğe kaydetme devre dışı bırakıldı.
MySQL:
- Reçeteli innodb_flush_method = O_DSYNC (kayıt hızının artması, dolayısıyla güvenilirliğin azalması).
- Günlük kaydı devre dışı bırakıldı, günlüklere ihtiyacımız yok.
- Reçeteli innodb_buffer_pool_size = 4G (InnoDB havuz boyutu ne kadar küçük olursa, MySQL durdurulduğunda o kadar hızlı kapanır ve anlık görüntü o kadar hızlı oluşturulur).
Bu, özellikle MySQL için tam bir liste değildir. Ancak geri kalan değişiklikler küçüktür ve çoğu zaman her zaman veya doğru şekilde uygulanamaz. Örneğin, diskleri boşaltma girişiminde bulunduk, hatta götürdük innodb_parallel_doublewrite_path /dev/shm'de, bu bazı durumlarda yanlış sonlandırılan bir örneği başlatırken bize 5 saniyeye kadar zaman kazandırdı.
Anlık görüntü almadan önce neden MySQL'i durduruyoruz? Sonuçta onu çalışan bir kopyadan kaldırabiliriz. Aynen öyle, ancak bu anlık görüntüdeki yeni veritabanı örneği varsayılan olarak hasarlı kabul edilecek ve başlangıçta tam tarama yapılması gerekecek. Bir kopyayı durdurmak kesinlikle daha hızlıdır, ancak bu tüm süreç içindeki en uzun işlemdir.
Bunun sonucunda daha kabul edilebilir zamanlamalar ve kullanıma hazır bir stand elde ettik. Ana kopyanın çoğaltma gecikmesinin en anlamlı grafiğinden de görülebileceği gibi, durum hala ideal olmaktan uzaktır:

Diğer eksikliklerin yanı sıra, İnce LVM havuzunu izlemenin pratik imkansızlığına dikkat etmek önemlidir: sistem standart iostat işlevlerine ek olarak, örneğin hangi havuz öğesinin şu anda dosya sistemi üzerinde en büyük yükü ürettiğini anlamak imkansızdır.
Ayrı olarak, yukarıda açıklanan optimizasyonla ilgili büyük bir dezavantajı da belirtmekte fayda var: bir YOLO standı aldık. Yaklaşık bir veya iki ayda bir ext4 bu tür suiistimallere dayanamadı ve onarılamaz şekilde bozuldu, bu da kopyanın yeniden biçimlendirilmesini ve yeniden yüklenmesini gerektirdi. Hızla kazanarak istikrarı umutsuzca bozduk.
Thin LVM kullanırken hangi ölçümleri izlemelisiniz:
- İnce havuz verileri %'si
- İnce havuz meta verileri %'si
Standımız veri için yer kalmaması durumunda hayatta kalırsa (diskleri temizlemek yeterlidir), o zaman meta veriler için yer kalmaması havuzun tamamen çökmesine ve onu sıfırdan yeniden oluşturma ihtiyacına yol açacaktır.
Havuz içindeki dosya sistemi zamanla çok parçalı hale gelir. Cron komutunu günde bir kez çalıştırmanızı öneririm fstrim -v /var/lib/mysql.
Alt toplamlar:
- Teknolojinin uygulanması tıpkı LVM gibi kolaydır ve özel mühendis vasıfları gerektirmez.
- Küçük ve çok yüklü olmayan veritabanları için çok uygundur. Veritabanı ne kadar küçük olursa, havuz içindeki dosya sisteminde o kadar az parça hareket eder ve disklerdeki yük de o kadar az olur.
- Görevimiz için bir sonraki bölümde tartışılacak olan diğer çözümleri aramaya başladık.
İkinci stand, ZFS teknolojisi
Uzun zaman önce ZFS dosya sistemiyle çalışıyordum, ancak o zamanlar ZFS, kendi Solaris işletim sistemi ailesinde güvenilir bir şekilde çalışıyordu. Oldukça iyi bir uygulama seviyesine sahip bir FreeBSD portu da vardı. Ayrıca tamamlanmamış bir portu da mevcuttu. LinuxÇok az kişinin kullandığı ZFS, B-ağacı veri depolama yapısı nedeniyle (bu arada, MySQL'in InnoDB'si de aynı depolama yapısına sahip), çok sayıda dosyaya sahip kurulumlarda kötü performans gösterdi. Bu durum, kullanımdan önce temel bilgileri öğrenme ihtiyacıyla birleşince, bu dosya sistemini uzun süre kullanmama neden oldu. Ext4 ve xfs ortaya çıktı ve standart haline geldi. Ancak ZFS'nin ihtiyaçlarımız için fazlasıyla uygun olduğu göz önüne alındığında, LinuxYorumlara bakılırsa, bu sürüm tamamen mantıklı bir ürün haline gelmiş (tam olarak desteklenmese de, bu nedenle ZFS üzerine sıfırdan bir sistem kurmak ancak çeşitli sihirli teknikler yardımıyla mümkün oluyor), biz de denemeye karar verdik.
Açık nedenlerden dolayı, stand benzer bir konfigürasyonla seçildi (RAID denetleyicisi hariç). Sekiz adet 1920 GB SSD sürücü kurduk. Sunucuyu çıplak ZFS'ye yüklemek için kendi ağ imajımızı yazma isteği yoktu, bu yüzden tüm disklerin 50 GB'ını kestik ve sistem için üzerlerine MD RAID-10 yaptık. Her diskte kalan 1950 GB, RAID-10'un ZFS analogunda birleştirildi:
zpool create zpool mirror /dev/sda2 /dev/sdb2 mirror /dev/sdc2 /dev/sdd2 mirror /dev/sde2 /dev/sdf2 mirror /dev/sdg2 /dev/sdh2MySQL için bölümler oluşturduk:
zfs create zpool/mysql
zfs set compression=gzip zpool/mysql
zfs set recordsize=128k zpool/mysql
zfs set atime=off zpool/mysql
zfs create zpool/mysql/data
zfs set recordsize=16k zpool/mysql/data
zfs set primarycache=metadata zpool/mysql/data
zfs set mountpoint=/var/lib/mysql zpool/mysql/dataYerel gzip veri sıkıştırmasını etkinleştirdiğimizi lütfen unutmayın. Sunucuda çok fazla işlemci kaynağımız var ve bunlar tam olarak kullanılmıyor, sonuç olarak veritabanımızın 3 TB'ı 1,6 TB'a dönüştü ve zayıf halka, önceki durumda olduğu gibi, maksimum disk performansı olduğundan, ne kadar az veri o kadar iyi. En başından beri ZFS'den harika bir bonus alıyoruz! Yoğun saatlerde tam yükte gzip'in çalışmaya devam etmesi 4 çekirdeğe kadar sürer, ancak bu bizim için sorun değil.
Daha sonra uygulama daha hızlı ilerledi. MySQL replika ayarları LVM standından karbon kopya olarak aktarıldı. ZFS komutlarını kullanarak komut dosyalarını yeniden yazmak için biraz zaman harcamak zorunda kaldım, ancak genel olarak algoritmalar aynı kaldı. Anlık görüntü oluşturmaya bir örnek:
zfs set snapdir=visible zpool/mysql/data
zfs create zpool/stage_3307
zfs clone zpool/mysql/data@snapmain zpool/stage_3307/data
zfs set mountpoint=/mnt/stage_3307 zpool/stage_3307/dataEk ayarlamalardan: meta veriler ve l2arc ve zil günlükleri içeren ZFS bölümlerini belleğe taşıdık. Daha sonra ortaya çıktığı gibi, görevimiz için bu gereksizdi, ancak şimdilik bu optimizasyonu bıraktık; gerekirse değiştirmek kolaydır. Olumsuz etkilerden biri, sunucuyu yeniden başlattıktan sonra ilgili bellek alanlarını yeniden oluşturmanız gerekmesidir. Hiçbir veri kaybolmaz. Zpool durum kırpması:
logs
/dev/shm/zil_slog.img ONLINE 0 0 0
cache
/dev/shm/l2arc.img ONLINE 0 0 0Bu yapılandırmada, standı test etmeye başladık ve mükemmel sonuçlar elde ettik: anlık görüntülerde aynı anda çalışan iki veritabanı örneği (ve etkin bir ana kopya) ile %50-60 disk kullanımı elde ettik.
Replikasyon gecikmesi grafiğinde de görülebileceği gibi ana sorunumuzdan kurtulduk (İnce LVM bölümündeki önceki grafikle karşılaştırın):

Buna ek olarak ve bu sayede tüm işlemleri büyük ölçüde hızlandırdık: bir kopyayı durdurup başlatarak tamamen anlık görüntü oluşturmak 40 saniyeye kadar sürer, anlık görüntüden yeni bir MySQL örneğini dağıtmak 20 saniyeye kadar sürer. Bu hem bizim hem de program kodu testlerimiz için fazlasıyla tatmin edicidir.
Alt toplamlar:
- Sonuçlar, kodu test etmek için üretim veritabanının bir kopyasını alma ihtiyacımızı tamamen karşıladı.
- Teknoloji giriş gerektirir: ZFS'nin ne olduğunu ve onunla nasıl çalışılacağını anlamanız gerekir.
- Çok sayıda (1 milyondan fazla) küçük dosya içeren ZFS'nin mevcut durumunu kontrol etmedik. Ancak sorunun devam ettiğini varsayıyoruz, bu nedenle bu dosya sistemini herhangi bir dosya depolama alanı için önermiyorum.
Sırada ne var?
Stand çerçevesinde yapacak başka bir şeyimiz yok; sonuçtan memnunuz. Belki gelecekte stand çoğaltma kurulumuna test için gerekli olmayan tabloların hariç tutulmasını ekleyeceğiz; bu, veritabanının boyutunu daha da azaltacaktır. BTRFS sistemini ve onun ince artıklık teknolojisi uygulamasını test etmedik. Ancak asıl hedefe ulaşıldığı için böyle bir göreve artık değmez. Genel olarak elbette yukarıda açıklanan yaklaşımdan uzaklaşmak istiyorum - çalışan veritabanı geçişlerini bir test ortamına uygulayın, ayrı bir test veritabanı devresi oluşturun ve ana veritabanını parçalamaya başlayın. Gelecek makalelerde mutlaka konuşacağımız üzere, bunların çoğunu zaten uygulamaya koyuyoruz.
sonuçlar
Orijinal sorun alışılmadık bir şekilde de olsa çözüldü. Ara sonuçlar, kullanılan teknolojilerin her birinin avantajlarını ve dezavantajlarını açıkladı; o halde hangi teknolojinin ne zaman kullanılabileceğine karar verelim:
- İnce LVM - küçük veritabanları için ve ZFS'yi öğrenmek istemediğinizde veya zamanınız olmadığında.
- ZFS - onunla çalışma deneyiminiz varsa veya herhangi bir durumda onu incelemek için zaman harcama fırsatınız varsa.
Daha yüksek bir sunum düzeyinde, bu makale yalnızca iki dosya sisteminin teknolojisinin bir karşılaştırması değildir. Aktarmak ve pekiştirmek istediğim ana fikir, iş açısından kritik durumlarda kalıpların dışında düşünmekten korkmamanız ve yalnızca hazır tarifler almanız gerektiğidir. Bir zamanlar teknik departmanda bir bütün olarak kafamızı sallayıp bir veritabanının üç terabaytlık kopyasını bir dakikadan kısa sürede oluşturma görevinin imkansız olduğunu ve riskli teknolojilere ihtiyacımız olmadığını söyleyebilirdik, hadi yapalım O doğru. Mümkündü, ancak test etmeseydik ve uygulama sırasında yaklaşık altı aydan bir yıla kadar ve çok sayıda müşteri gezisini (seyahat bizim ana iş göstergemizdir) kaybederdik. Kalıpların dışında hareket ederek uygulama konusunda fazla zaman kaybetmedik, yeni ve unutulmuş eski teknolojiler konusunda deneyim kazandık ve gerçekten ihtiyaç duyduğumuz bir zamanda test imkanı sağladık. Kuşkusuz bu durum tüm göstergelerimize olumlu yansıdı. Seçim her zaman sizin ve biz de blogumuzda mevcut ve gelecekteki ilginç başarılardan bahsetmeye devam edeceğiz.
Kaynak: habr.com
