· kaynak dev.to (home feed)
Redis 8.12-rc1, Roaring Bitmaps'i çekirdeğe taşıyor; seyrek bitmap belleğini 24MB'dan 239KB'ya düşürüyor
Redis 8.12-rc1, Roaring Bitmaps'i ayrı bir projeden sunucunun çekirdeğine taşıyor; opsiyonel bir temsil ve yeni BITRANGEINTARRAY komutuyla geliyor. Bağımsız testler seyrek bitmaplerde 103 kat bellek azalması gösteriyor; yoğun bitmapler ise hafifçe büyüyor.

Redis 8.12-rc1, Roaring Bitmaps'i sunucuya getiriyor
Redis 8.12-rc1, daha önce ayrı bir proje olan redis-roaring'ı sunucunun kendisine dahil ediyor. Sürüm, bitmaplere instance'ların yeni bitmap-default-roaring ayarıyla etkinleştirebileceği ikinci, opsiyonel bir iç temsil kazandırıyor; ayrıca bir aralıktaki set edilmiş bitlerin offset'lerini doğrudan döndüren BITRANGEINTARRAY komutuyla geliyor. dev.to'daki bir uygulamalı yazıya göre sürüm notları, bu değişikliği belleği azaltmak ve bitmap işlemlerini hızlandırmak için bir yol olarak sunuyor — seyrek, gerçekçi biçimli veriler üzerindeki ölçümler bunu çarpıcı biçimde doğruluyor; yoğun veri ve mevcut kod için ise önemli uyarılar var.
Seyrek bitmapler yaklaşık yüz kat küçülüyor
dev.to yazarı, yaygın bir üretim desenini yansıtan bir biçimde kıyasladı: 200 milyon olası kullanıcı ID'sinden belirli bir günde yaklaşık 20.000 tanesinin aktif olması. Somut olarak, aynı rastgele tohumla iki kez, 200.000.000 bitlik bir aralıkta pseudo-rastgele offset'lerde 20.000 bit set edildi; böylece legacy ve roaring anahtarları aynı bitleri işaret ediyor.
MEMORY USAGE, legacy bitmap için 25.165.860 bayt — yaklaşık 24MB — roaring olan için ise 244.837 bayt — yaklaşık 239KB — bildirdi; bu, yaklaşık 103 kat küçük demek. OBJECT ENCODING ikisini raw ve bitmap-roaring olarak ayırt ediyor.
Tüm değeri tarayan BITCOUNT da hızlandı: üç kıyas turunda legacy bitmap'te saniyede 1.040–1.056 istek, roaring'de ise 14.706–15.152 istek; yaklaşık 14 kat kazanç. Yazıya göre bu, doğrudan veri yapısından kaynaklanıyor: set edilmiş bitleri saymak, değeri bayt bayt taramak yerine yapının container'larını dolaşmak anlamına geliyor.
Yoğun bitmapler pek fayda görmüyor
Roaring Bitmaps, kümelenmiş ardışıklıkları ve seyrek kümeleri sıkıştırır. Bitlerinin yaklaşık yarısı set edilmiş ve deseni olmayan bir bitmapte sıkıştırılacak bir şey yok. Yazar, her çift bitin set edildiği 1.000.000 bitlik bir değeri test etti — run-length encoding için kolay bir durum — ve yine de roaring altında biraz daha büyük çıktı: 131.103 bayta karşı 132.376 bayt, yaklaşık %1 kötü. Yoğun çift üzerinde BITCOUNT verimi neredeyse aynıydı: legacy için saniyede 23.622–25.000 istek, roaring için 26.087–27.778 istek; çünkü 125KB'lık bir tarama zaten hızlıydı.
Bir string encoding'i değil, ayrı bir tür
Operasyonel olarak en büyük ağırlığı taşıyan ayrıntı şu: roaring bitmap, listpack veya intset'in diğer türlerin encoding'i olması gibi string türünün başka bir encoding'i değil. Roaring bir anahtar üzerinde TYPE, bitmap bildiriyor ve Redis bu sınırı zorluyor. String odaklı komutlar — GETRANGE, APPEND, SETRANGE, STRLEN — roaring bir anahtarda WRONGTYPE hatası verirken; GETBIT, BITCOUNT, BITFIELD ve BITOP dahil bit odaklı aile eskisi gibi davranıyor. BITOP, aynı işlemde roaring bir anahtar ile legacy, string tabanlı bir bitmapi birlikte kabul ediyor bile.
Bu sınır, gerçek kodda var olan bir desen için sessiz bir kırılma yaratıyor: bayrakları SETBIT ile bir anahtara yazıp sonra GETRANGE ile geri okumak. Yeni varsayılan açıldığında, ilk yeni anahtar roaring yolunu izliyor ve bu string okumaları başarısız olmaya başlıyor.
Bilinmesi gereken geçiş ve uç davranışlar
bitmap-default-roaring ayarı yalnızca bir anahtar oluşturulurken danışılıyor. Kapatmaya geri çevirmek mevcut roaring anahtarlarına dokunmuyor; yazar, bir bitmapi temsiller arasında yerinde dönüştüren bir komut bulamadı — geçiş, bir anahtarı okuyup diğer ayar altında yeniden inşa etmek anlamına geliyor.
BITRANGEINTARRAY yeni türle sınırlı değil. Legacy bitmaplerde ve düz stringlerde de çalışıyor; stringlerde, Redis'in diğer bit komutlarının stringlere davrandığıyla uyumlu biçimde ASCII encoding'inin set edilmiş bitlerini döndürüyor. Kötü girdi için de asla hata döndürmüyor: var olmayan anahtarlar ve ters aralıklar boş diziler üretiyor, negatif bir bitiş değeri GETRANGE'in yorumladığı gibi yorumlanıyor ve bitmapin uzunluğunun çok ötesindeki bir bitiş değeri kırpılıyor. Bu bağışlayıcı; ama bir aralık aritmetiği hatasının — örneğin küçük bir pozitif değer beklerken negatif bir değer geçmenin — sessizce yanlış sayıda sonuç döndürmesi anlamına geliyor.
Bir de sürümleme tuzağı var. 8.12-rc1 için henüz resmi bir Docker imajı yok ve etiketli kaynaktan yapılan bir build, INFO server üzerinden kendini 8.11.240 sürümü olarak tanıtıyor — sürüm etiketinin tam bir minor sürüm gerisinde — bu da bildirilen sürüme göre özellik açan herhangi bir script'i yanıltabilir.
Neden önemli
Devasa ID uzayları üzerinden anahtarlanmış bitmapler — günlük aktif kullanıcılar, özellik bayrakları, tekilleştirme kümeleri — köklü bir Redis desenidir ve burada test edilen seyrek biçim de yaygın olanıdır. Yüz kat bellek azalması ve 14 kat daha hızlı tam tarama, daha önce karşılanamayan bazı iş yüklerini karşılanabilir hale getirebilir. Ancak takas iş yüküne bağlı: yoğun bitmapler küçük bir ceza ödüyor, mevcut anahtarlar yerinde dönüştürülemiyor ve yeni tür sınırı string komutu kullanımını uyarısız kırabiliyor. Rakamlar ayrıca resmi Redis verilerinden değil tek bir bağımsız kıyastan geliyor; ekipler varsayılanı etkinleştirmeden önce kendi veri biçimleriyle doğrulamalı — ve bir release candidate etrafında script yazmadan önce sürümlemenin oturmasını beklemeliler.
- #redis
- #databases
- #data-structures
- #performance
- #memory-optimization