Redis'in yazarı Salvatore Sanfilippo, bir zamanlar bu iki bellek tabanlı veri depolama sistemini karşılaştırdı:
Özellikle yukarıdaki sonucun neden ortaya çıktığı, aşağıdaki toplanan verilerdir:
1. Farklı veri türleri desteği
Yalnızca basit bir anahtar-değer yapısıyla veri kayıtlarını destekleyen Memcached'in aksine, Redis çok daha zengin veri türlerini destekler. En sık kullanılan beş veri türü vardır: Dize, Karma, Liste, Küme ve Sıralı Küme. Redis dahili olarak tüm anahtarları ve değerleri temsil etmek için bir redisObject nesnesi kullanır. RedisObject'in ana bilgileri şekilde gösterilmektedir:
Tür, bir değer nesnesinin belirli veri türünü temsil eder. Kodlama, redis'deki farklı veri türlerinin depolama yöntemidir. Örneğin: tür = dizge, değerin sıradan bir dizeyi sakladığını gösterir, böylece karşılık gelen kodlama ham veya int olabilir. Bu bir int ise, gerçek redis dizgesini sayısal türe göre dahili olarak depolayıp temsil ettiği anlamına gelir.Elbette, öncül dizenin kendisinin bir sayısal değerle temsil edilebilmesidir, örneğin: "123" "456". Sadece Redis'in sanal bellek işlevi açıldığında, vm alanı gerçekten bellek ayıracaktır Bu işlev varsayılan olarak kapalıdır.
1) Dize
2) Karma
3) Liste
4) Ayarla
5) Sıralanmış Set
2. Farklı bellek yönetimi mekanizmaları
Redis'te tüm veriler her zaman bellekte depolanmaz. Memcached ile karşılaştırıldığında en büyük fark budur. Fiziksel bellek tükendiğinde, Redis uzun süredir kullanılmayan bazı değerleri diske takas edebilir. Redis yalnızca tüm anahtarların bilgilerini önbelleğe alır. Redis, bellek kullanımının belirli bir eşiği aştığını tespit ederse, takas işlemini tetikler. Redis, "swappability = age * log (size_in_memory)" uyarınca gereken değere hangi anahtarların karşılık geldiğini hesaplar diske takas. Daha sonra bu anahtarlara karşılık gelen değerler diskte saklanır ve aynı zamanda bellekten silinir. Bu özellik, Redis'in makinenin kendi bellek boyutunu aşan verileri korumasına izin verir. Elbette, makinenin kendi hafızası tüm anahtarları tutabilmelidir, sonuçta bu veriler değiştirilmeyecektir. Aynı zamanda, Redis bellekteki verileri diske takas ettiğinde, hizmeti sağlayan ana iş parçacığı ve takas işlemini gerçekleştiren alt iş parçacığı, belleğin bu bölümünü paylaşacaktır, bu nedenle, takas gerektiren veriler güncellenirse, Redis bu işlemi alt iş parçacığına kadar engelleyecektir. Takas işlemi tamamlandıktan sonra değişiklik yapılabilir. Redis'ten veri okurken, okuma anahtarına karşılık gelen değer bellekte değilse, Redis'in karşılık gelen verileri takas dosyasından yüklemesi ve ardından bunu istemciye iade etmesi gerekir. Burada bir G / Ç iş parçacığı havuzu sorunu var. Varsayılan olarak Redis engelleyecektir, yani tüm takas dosyaları yüklendikten sonra yanıt verecektir. Bu strateji, müşteri sayısı az olduğunda ve toplu işlemler gerçekleştirildiğinde daha uygundur. Ancak Redis, büyük ölçekli bir web sitesi uygulamasına uygulanırsa, bu açıkça büyük eşzamanlılık durumunu karşılayamaz. Böylece Redis çalıştırır, G / Ç iş parçacığı havuzunun boyutunu belirleriz ve engelleme süresini azaltmak için takas dosyasından karşılık gelen verileri yüklemesi gereken okuma istekleri üzerinde eşzamanlı işlemler gerçekleştiririz.
Redis ve Memcached gibi bellek tabanlı veritabanı sistemleri için bellek yönetiminin verimliliği, sistem performansını etkileyen önemli bir faktördür. Geleneksel C dilindeki malloc / free işlevi, bellek ayırma ve serbest bırakmada en yaygın kullanılan yöntemdir, ancak bu yöntemin büyük kusurları vardır: birincisi, geliştiriciler için uyumsuz malloc ve free bellek sızıntılarına neden olabilir; ikincisi Sık çağrılar, çok sayıda bellek parçasının geri dönüştürülememesine ve yeniden kullanılamamasına neden olarak bellek kullanımını azaltır; Son olarak, bir sistem çağrısı olarak, sistem yükü genel işlev çağrılarınınkinden çok daha fazladır. Bu nedenle, bellek yönetiminin verimliliğini artırmak için verimli bellek yönetimi çözümleri, malloc / ücretsiz aramaları doğrudan kullanmayacaktır. Hem Redis hem de Memcached kendi tasarlanmış bellek yönetimi mekanizmalarını kullanır, ancak uygulama yöntemlerinde büyük farklılıklar vardır. İkisinin bellek yönetimi mekanizmaları aşağıda ayrı ayrı tanıtılacaktır.
Memcached varsayılan olarak belleği yönetmek için Döşeme Tahsisi mekanizmasını kullanır Ana fikir, bellek parçalanma problemini tamamen çözmek için karşılık gelen uzunluktaki anahtar-değer veri kayıtlarını depolamak için tahsis edilen belleği önceden belirlenmiş bir boyuta göre belirli bir uzunluktaki bloklara bölmektir. Döşeme Tahsis mekanizması yalnızca harici verileri depolamak için tasarlanmıştır; yani, tüm anahtar-değer verileri Döşeme Tahsis sisteminde saklanırken, Memcached'in diğer bellek istekleri sıradan malloc / free aracılığıyla uygulanır, çünkü bu taleplerin sayısı ve Frekans, tüm sistemin performansını etkilemeyeceğini belirler Döşeme Tahsisi prensibi oldukça basittir. Şekilde gösterildiği gibi, öncelikle işletim sisteminden büyük bir bellek bloğu için geçerlidir ve onu çeşitli boyutlarda parçalara böler ve aynı boyuttaki blokları Döşeme Sınıfı gruplarına ayırır. Bunların arasında Chunk, anahtar-değer verilerini depolamak için kullanılan en küçük birimdir. Her Slab Sınıfının boyutu, Memcached başlatıldığında Büyüme Faktörü ayarlanarak kontrol edilebilir. Şekildeki Büyüme Faktörünün değerinin 1,25 olduğunu varsayarsak, birinci öbek grubunun boyutu 88 bayt ise, ikinci öbek grubunun boyutu 112 bayttır, vb.
Memcached, müşteri tarafından gönderilen verileri aldığında, önce alınan verinin boyutuna göre en uygun Döşeme Sınıfını seçecek ve ardından Memcached tarafından kaydedilen Döşeme Sınıfı'ndaki boş yığınların listesini veri depolamak için kullanılabilecek bir tane bulmak için sorgulayacaktır. Parçacık. Bir veritabanının süresi dolduğunda veya atıldığında, kaydın işgal ettiği yığın geri dönüştürülebilir ve boş listeye yeniden eklenebilir. Yukarıdaki süreçten Memcached'in bellek yönetim sisteminin verimli olduğunu ve bellek parçalanmasına neden olmayacağını görebiliriz ancak en büyük dezavantajı alan israfına neden olmasıdır. Her Chunk'a belirli uzunlukta bir bellek alanı tahsis edildiğinden, değişken uzunluklu veriler bu alanı tam olarak kullanamaz. Şekilde gösterildiği gibi, 100 bayt veri 128 baytlık bir Chunk içinde arabelleğe alınırsa, kalan 28 bayt boşa harcanır.
Redis'in bellek yönetimi esas olarak kaynak koddaki iki dosya zmalloc.h ve zmalloc.c aracılığıyla gerçekleştirilir. Bellek yönetimini kolaylaştırmak için Redis, bir bellek bloğu tahsis ettikten sonra bu belleğin boyutunu bellek bloğunun başına kaydeder. Şekilde gösterildiği gibi, real_ptr, redis malloc'u çağırdıktan sonra döndürülen göstericidir. Redis, bellek bloğunun boyutunu başlıkta depolar ve boyut tarafından kaplanan bellek boyutu bilinir, bu boyut_t türünün uzunluğu ve ardından ret_ptr'yi döndürür. Belleğin serbest bırakılması gerektiğinde, ret_ptr bellek yönetimi programına geçirilir. Ret_ptr aracılığıyla, program real_ptr değerini kolayca hesaplayabilir ve ardından belleği serbest bırakmak için real_ptr'yi serbest bırakabilir.
Redis, bir dizi tanımlayarak tüm bellek ayırmalarını kaydeder.Bu dizinin uzunluğu ZMALLOC_MAX_ALLOC_STAT'dir. Dizinin her bir öğesi, geçerli program tarafından ayrılan bellek bloklarının sayısını temsil eder ve bellek bloğunun boyutu, öğenin alt simgesidir. Kaynak kodda bu dizi zmalloc_allocations şeklindedir. zmalloc_allocations, 16 bayt uzunluğunda ayrılmış bellek bloklarının sayısını temsil eder. Zmalloc.c dosyasında, şu anda ayrılmış belleğin toplam boyutunu kaydetmek için kullanılan statik bir değişken vardır. Bu nedenle, genel olarak Redis, Memcached'in bellek yönetimi yönteminden çok daha basit olan paketlenmiş mallc / free kullanır.
3. Veri kalıcılığı desteği
Redis, bellek tabanlı bir depolama sistemi olmasına rağmen, bellek içi verilerin kalıcılığını destekler ve iki ana kalıcılık stratejisi sağlar: RDB anlık görüntüleri ve AOF günlükleri. Memcached, veri kalıcılığı işlemlerini desteklemez.
1) RDB anlık görüntüsü
Redis, mevcut verilerin anlık görüntüsünü bir veri dosyası, yani bir RDB anlık görüntüsü olarak kaydeden bir kalıcılık mekanizmasını destekler. Ancak sürekli yazılan bir veritabanı nasıl bir anlık görüntü oluşturur? Redis, fork komutunun yazma mekanizmasına kopyasını kullanır. Bir anlık görüntü oluştururken, mevcut işlemi bir alt işleme ayırın, ardından alt işlemdeki tüm verileri döngüleyin ve verileri bir RDB dosyasına yazın. Redis'in kaydetme komutu ile RDB anlık görüntü oluşturma zamanlamasını yapılandırabiliriz.Örneğin, 10 dakika içinde bir anlık görüntü oluşturacak şekilde yapılandırılabilir veya 1000 yazma sonrasında bir anlık görüntü oluşturacak şekilde yapılandırılabilir veya birden fazla kural birlikte uygulanabilir. Bu kuralların tanımı Redis yapılandırma dosyasındadır.Redis, Redis'i yeniden başlatmadan Redis'in CONFIG SET komutu aracılığıyla çalışırken de kuralları ayarlayabilirsiniz.
Redis'in RDB dosyası, yazma işlemi yeni bir işlemde gerçekleştirildiği için kırılmayacaktır.Yeni bir RDB dosyası oluşturulduğunda, Redis tarafından oluşturulan alt süreç önce verileri geçici bir dosyaya yazar ve ardından atomu kullanır Cinsel yeniden adlandırma sistem çağrısı, geçici dosyayı RDB dosyası olarak yeniden adlandırır, böylece Redis RDB dosyası bir arıza olduğunda her zaman kullanılabilir olur. Aynı zamanda, Redis RDB dosyaları da Redis ana-bağımlı senkronizasyonunun dahili uygulamasının bir parçasıdır. RDB'nin eksiklikleri vardır.Veritabanında bir sorun olduğunda, RDB dosyamızda saklanan veriler yepyeni değildir ve son RDB dosyası oluşturmadan Redis'in kapatılmasına kadar tüm veriler kaybolur. Bazı işyerlerinde bu tolere edilebilir.
2) AOF günlüğü
AOF günlüğünün tam adı, eklenen bir günlük dosyası olan yalnızca dosyaya eklenir. Genel bir veritabanının binlog'undan farklı olarak, AOF dosyası tanınabilir bir düz metindir ve içeriği bir Redis standart komutudur. Yalnızca verilerin değiştirilmesine neden olacak komutlar AOF dosyasına eklenecektir. Verileri değiştirmeye yönelik her komut bir günlük oluşturur ve AOF dosyası giderek büyür, bu nedenle Redis, AOF yeniden yazma adı verilen başka bir işlev sağlar. İşlevi, bir AOF dosyasını yeniden oluşturmaktır.Yeni AOF dosyasındaki bir kaydın işlemi, aynı değerde birden çok işlemi kaydedebilen eski bir dosyanın aksine, yalnızca bir kez yapılacaktır. Oluşturma süreci RDB'ye benzer ve aynı zamanda verileri doğrudan geçen ve yeni AOF geçici dosyaları yazan bir çatal işlemidir. Yeni bir dosya yazma sürecinde, tüm yazma işlemi günlükleri yine de orijinal eski AOF dosyasına yazılacak ve ayrıca bellek arabelleğine kaydedilecektir. Yeniden işlem tamamlandığında, tüm arabelleklerdeki günlükler bir seferde geçici dosyaya yazılacaktır. Ardından eski AOF dosyasını yeni AOF dosyasıyla değiştirmek için atomic rename komutunu çağırın.
AOF, amacı işlem günlüğünü diske yazmak olan bir dosya yazma işlemidir, bu nedenle yukarıda bahsettiğimiz yazma işlemi süreciyle de karşılaşacaktır. Redis'te AOF'ye yazma çağrıldıktan sonra, appendfsync seçeneği fsync'in diske yazılması için çağrılma süresini kontrol etmek için kullanılır.Apendfsync'in aşağıdaki üç ayarı giderek daha güçlü hale geldi.
Genel iş gereksinimleri için, RDB ek yükü AOF günlüklerinden çok daha düşük olduğundan kalıcılık için RDB kullanılması önerilir.Veri kaybına dayanamayan uygulamalar için, AOF günlüklerinin kullanılması önerilir.
4. Küme yönetimindeki fark
Memcached, tam bellekli bir veri arabellek sistemidir. Redis, veri kalıcılığını desteklese de, tam bellek yüksek performansının özüdür. Belleğe dayalı bir depolama sistemi olarak, makinenin fiziksel belleğinin boyutu, sistemin tutabileceği maksimum veri miktarıdır. İşlenecek veri miktarı tek bir makinenin fiziksel bellek boyutunu aşarsa, depolama kapasitesini genişletmek için dağıtılmış bir kümenin oluşturulması gerekir.
Memcached'in kendisi dağıtımı desteklemez, bu nedenle tutarlı hashing gibi dağıtılmış algoritmalar yalnızca Memcached'in istemci tarafında dağıtılmış depolamasını gerçekleştirmek için kullanılabilir. Aşağıdaki şekil Memcached'in dağıtılmış depolama uygulama mimarisini göstermektedir. İstemci Memcached kümesine veri göndermeden önce, ilk olarak yerleşik dağıtılmış algoritma aracılığıyla verilerin hedef düğümünü hesaplayacak ve ardından veri depolama için doğrudan düğüme gönderilecektir. Bununla birlikte, müşteri verileri sorguladığında, sorgu verilerinin bulunduğu düğümü de hesaplaması ve ardından verileri elde etmek için düğüme doğrudan bir sorgu isteği göndermesi gerekir.
Dağıtılmış depolamayı uygulamak için yalnızca istemciyi kullanabilen Memcached ile karşılaştırıldığında Redis, sunucu tarafında dağıtılmış depolama oluşturmaya daha meyillidir. Redis'in en son sürümü zaten dağıtılmış depolamayı desteklemektedir. Redis Cluster, dağıtılmış uygulayan ve tek hata noktalarına izin veren gelişmiş bir Redis sürümüdür. Merkezi bir düğüme sahip değildir ve doğrusal ölçeklenebilirliğe sahiptir. Aşağıdaki şekil, düğümlerin ikili protokol aracılığıyla birbirleriyle ve düğümler ile istemci arasında ascii protokolü aracılığıyla iletişim kurduğu Redis Cluster'ın dağıtılmış depolama mimarisini gösterir. Veri yerleştirme stratejisi açısından, Redis Kümesi, tüm anahtar değeri alanını 4096 karma yuvasına böler ve her düğüm bir veya daha fazla karma yuvası depolayabilir, bu da Redis Kümesi tarafından desteklenen mevcut maksimum düğüm sayısının 4096 olduğu anlamına gelir. Redis Cluster tarafından kullanılan dağıtılmış algoritma da çok basittir: crc16 (anahtar)% HASH_SLOTS_NUMBER.
Redis Cluster, tek bir arıza noktası altında veri kullanılabilirliğini sağlamak için Ana düğümü ve Bağımlı düğümü sunar. Redis Kümesinde, her bir Ana düğüm, yedeklilik için karşılık gelen iki Bağımlı düğüme sahip olacaktır. Bu şekilde, kümenin tamamında, herhangi iki düğümün kesinti süresi, verilerin kullanılamamasına neden olmaz. Ana düğüm çıktığı zaman, küme yeni Ana düğüm olmak için otomatik olarak bir Bağımlı düğüm seçecektir.