Aracılığıyla paylaş


Önbelleğe alma kılavuzu

Azure Yönetilen Redis

Önbelleğe alma, bir sistemin performansını ve ölçeklenebilirliğini artırmayı amaçlayan yaygın bir tekniktir. Sık erişilen verileri uygulamaya yakın bir konumdaki hızlı depolama alanına geçici olarak kopyalayarak verileri önbelleğe alır. Bu hızlı veri depolama alanının konumu uygulamaya özgün kaynaktan daha yakınsa, önbelleğe alma işlemi verileri daha hızlı sunarak istemci uygulamaların yanıt sürelerini önemli ölçüde artırabilir.

Önbelleğe alma, özellikle aşağıdaki koşulların tümü özgün veri deposu için geçerliyse, istemci örneği aynı verileri tekrar tekrar okuduğunda etkili olur:

  • Nispeten statik kalır.
  • Önbellek hızıyla karşılaştırıldığında yavaştır.
  • Yüksek düzeyde bir çekişmeye tabidir.
  • Ağ gecikmesi erişimin yavaşmasına neden olabileceğinde çok uzaktır.

Dağıtılmış uygulamalarda önbelleğe alma

Dağıtılmış uygulamalar genellikle verileri önbelleğe alırken aşağıdaki stratejilerden birini veya ikisini birden uygular:

  • Bir uygulamanın veya hizmetin örneğini çalıştıran bilgisayarda verilerin yerel olarak tutulduğu özel bir önbellek kullanırlar.
  • Birden çok işlem ve makine tarafından erişilebilen ortak bir kaynak olarak hizmet veren paylaşılan bir önbellek kullanırlar.

Her iki durumda da önbelleğe alma işlemi istemci tarafında ve sunucu tarafında gerçekleştirilebilir. İstemci tarafı önbelleğe alma işlemi, web tarayıcısı veya masaüstü uygulaması gibi bir sistem için kullanıcı arabirimi sağlayan işlem tarafından gerçekleştirilir. Sunucu tarafı önbelleğe alma işlemi, uzaktan çalışan iş hizmetlerini sağlayan işlem tarafından gerçekleştirilir.

Özel önbelleğe alma

En temel önbellek türü bellek içi depodur. Tek bir işlemin adres alanında tutulur ve bu işlemde çalışan kod tarafından doğrudan erişilir. Bu önbellek türüne erişmek hızlı bir işlemdir. Ayrıca, mütevazı miktarda statik veri depolamak için etkili bir yol da sağlayabilir. Önbelleğin boyutu genellikle işlemi barındıran makinede kullanılabilir bellek miktarıyla kısıtlanır.

Bellekte fiziksel olarak mümkün olandan daha fazla bilgiyi önbelleğe almanız gerekiyorsa, önbelleğe alınmış verileri yerel dosya sistemine yazabilirsiniz. Bu işlem, bellekte tutulan verilere göre daha yavaş erişim sağlar, ancak yine de ağ üzerinden veri almaktan daha hızlı ve daha güvenilir olmalıdır.

Bir uygulamanın bu modeli aynı anda çalıştıran birden çok örneğiniz varsa, her uygulama örneğinin kendi veri kopyasını tutan kendi bağımsız önbelleği vardır.

Önbelleği, geçmişteki bir noktada özgün verilerin anlık görüntüsü olarak düşünün. Bu veriler statik değilse, büyük olasılıkla farklı uygulama örnekleri önbelleklerinde verilerin farklı sürümlerini barındırır. Bu nedenle, bu örnekler tarafından gerçekleştirilen sorgu, Şekil 1'de gösterildiği gibi farklı sonuçlar döndürebilir.

Bir uygulamanın farklı örneklerinde bellek içi önbellek kullanmanın sonuçları

Şekil 1: Bir uygulamanın farklı örneklerinde bellek içi önbellek kullanma.

Paylaşımlı önbellek

Paylaşılan bir önbellek kullanıyorsanız, verilerin her önbellekte farklılık gösterebileceği ve bellek içi önbelleğe alma ile ortaya çıkabilecek endişelerin hafifletilmesine yardımcı olabilir. Paylaşılan önbelleğe alma, farklı uygulama örneklerinin önbelleğe alınan verilerin aynı görünümünü görmesini sağlar. Şekil 2'de gösterildiği gibi önbelleği genellikle ayrı bir hizmetin parçası olarak barındırılan ayrı bir konumda bulur.

Paylaşılan önbellek kullanmanın sonuçları

Şekil 2: Paylaşılan önbellek kullanma.

Paylaşılan önbelleğe alma yaklaşımının önemli avantajlarından biri, sağladığı ölçeklenebilirliktir. Birçok paylaşılan önbellek hizmeti, bir sunucu kümesi kullanılarak uygulanır ve verileri kümeye saydam bir şekilde dağıtmak için yazılım kullanılır. Uygulama örneği, önbellek hizmetine bir istek gönderir. Temel alınan altyapı, önbelleğe alınan verilerin kümedeki konumunu belirler. Daha fazla sunucu ekleyerek önbelleği kolayca ölçeklendikleyebilirsiniz.

Paylaşılan önbelleğe alma yaklaşımının iki temel dezavantajı vardır:

  • Önbellek, artık her uygulama örneğinde yerel olarak tutulmadığından erişim daha yavaştır.
  • Ayrı bir önbellek hizmeti uygulama gereksinimi çözüme karmaşıklık katabilir.

Önbelleğe alma ile ilgili dikkat edilmesi gerekenler

Aşağıdaki bölümlerde, önbellek tasarlama ve kullanma ile ilgili dikkat edilmesi gerekenler daha ayrıntılı olarak açıklanmaktadır.

Verilerin ne zaman önbelleğe alıneceğine karar verme

Önbelleğe alma performansı, ölçeklenebilirliği ve kullanılabilirliği önemli ölçüde iyileştirebilir. Ne kadar çok veriniz varsa ve bu verilere erişmesi gereken kullanıcı sayısı o kadar fazlaysa, önbelleğe almanın avantajları o kadar artar. Önbelleğe alma, özgün veri deposundaki büyük hacimli eşzamanlı istekleri işlemeyle ilişkili gecikme süresini ve çekişmesini azaltır.

Örneğin, veritabanı sınırlı sayıda eşzamanlı bağlantıyı destekleyebileceğinden. Ancak, temel alınan veritabanı yerine paylaşılan bir önbellekten veri almak, kullanılabilir bağlantı sayısı tükenmiş olsa bile istemci uygulamasının bu verilere erişmesini mümkün kılar. Ayrıca, veritabanı kullanılamaz duruma gelirse istemci uygulamaları önbellekte tutulan verileri kullanarak devam edebilir.

Sık okunan ancak seyrek değiştirilen verileri önbelleğe almayı göz önünde bulundurun (örneğin, okuma işlemlerinin oranı yazma işlemlerinden daha yüksek olan veriler). Ancak, önbelleği kritik bilgilerin yetkili deposu olarak kullanmanızı önermeyiz. Bunun yerine, uygulamanızın kaybetmeyi göze alamayacakları tüm değişikliklerin her zaman kalıcı bir veri deposuna kaydedildiğinden emin olun. Önbellek kullanılamıyorsa, uygulamanız veri deposunu kullanarak çalışmaya devam edebilir ve önemli bilgileri kaybetmezsiniz.

Verilerin etkili bir şekilde nasıl önbelleğe alındığını belirleme

Önbelleği etkili bir şekilde kullanmanın anahtarı, önbelleğe alınacak en uygun verileri belirlemek ve uygun zamanda önbelleğe almaktır. Veriler, bir uygulama tarafından ilk kez alındığında isteğe bağlı olarak önbelleğe eklenebilir. Uygulamanın verileri veri deposundan yalnızca bir kez getirmesi gerekir ve sonraki erişim önbelleği kullanılarak karşılanabilir.

Alternatif olarak, önbellek genellikle uygulama başlatıldığında (tohumlama olarak bilinen bir yaklaşım) önceden kısmen veya tamamen verilerle doldurulabilir. Ancak, uygulama çalışmaya başladığında bu yaklaşım özgün veri deposuna ani ve yüksek yük getirebileceğinden büyük bir önbellek için tohumlama uygulanması önerilmez.

Genellikle kullanım desenlerinin analizi, önbelleğin tamamen mi yoksa kısmen mi önceden doldurulup doldurulmayacağına ve önbelleğe alınacak verileri seçmenize karar vermenize yardımcı olabilir. Örneğin, önbelleği, uygulamayı düzenli olarak (belki de her gün) kullanan ancak uygulamayı haftada yalnızca bir kez kullanan müşteriler için değil statik kullanıcı profili verileriyle görebilirsiniz.

Önbelleğe alma genellikle sabit olan veya seyrek değişen verilerle iyi çalışır. Örnek olarak e-ticaret uygulamasındaki ürün ve fiyatlandırma bilgileri gibi başvuru bilgileri veya oluşturması maliyetli paylaşılan statik kaynaklar verilebilir. Bu verilerin bir kısmı veya tamamı, kaynaklara olan talebi en aza indirmek ve performansı geliştirmek için uygulama başlangıcında önbelleğe yüklenebilir. Ayrıca, up-to-date olduğundan emin olmak için önbellekteki başvuru verilerini düzenli aralıklarla güncelleştiren bir arka plan işlemine sahip olmak isteyebilirsiniz. Alternatif olarak, başvuru verileri değiştiğinde arka plan işlemi önbelleği yenileyebilir.

Önbelleğe alma, dinamik veriler için daha az yararlıdır, ancak bu konuda bazı özel durumlar vardır (daha fazla bilgi için bu makalenin devamında yer alan Yüksek oranda dinamik verileri önbelleğe alma bölümüne bakın). Özgün veriler düzenli olarak değiştiğinde, önbelleğe alınan bilgiler hızla eskir veya önbelleği özgün veri deposuyla eşitleme yükü önbelleğe alma etkinliğini azaltır.

Önbelleğin bir varlığın tüm verilerini içermesi gerekmez. Örneğin, bir veri öğesi ad, adres ve hesap bakiyesi olan bir banka müşterisi gibi çok değerli bir nesneyi temsil ederse, bu öğelerden bazıları ad ve adres gibi statik kalabilir. Hesap bakiyesi gibi diğer öğeler daha dinamik olabilir. Bu gibi durumlarda, verilerin statik bölümlerini önbelleğe almak ve yalnızca gerekli olduğunda kalan bilgileri almak (veya hesaplamak) yararlı olabilir.

Önbelleğin önceden doldurulup doldurulmadığını veya isteğe bağlı olarak yüklenmesinin veya ikisinin bir bileşiminin uygun olup olmadığını belirlemek için performans testi ve kullanım analizi gerçekleştirmenizi öneririz. Karar, verilerin volatilitesine ve kullanım düzenine dayalı olmalıdır. Önbellek kullanımı ve performans analizi, ağır yüklerle karşılaşan ve yüksek oranda ölçeklenebilir olması gereken uygulamalarda önemlidir. Örneğin, yüksek oranda ölçeklenebilir senaryolarda yoğun zamanlarda veri deposundaki yükü azaltmak için önbelleğin dağıtımını yapabilirsiniz.

Önbelleğe alma, uygulama çalışırken hesaplamaların yinelenmemesi için de kullanılabilir. Bir işlem verileri dönüştürürse veya karmaşık bir hesaplama yaparsa, işlemin sonuçlarını önbelleğe kaydedebilir. Daha sonra aynı hesaplama gerekiyorsa uygulama sonuçları önbellekten alabilir.

Bir uygulama, önbellekte tutulan verileri değiştirebilir. Bununla birlikte, önbelleğin herhangi bir zamanda kaybolabilecek geçici bir veri deposu olarak düşünmenizi öneririz. Değerli verileri yalnızca önbellekte depolamayın; bilgileri özgün veri deposunda da sakladığınıza emin olun. Bu, önbellek kullanılamaz duruma gelirse veri kaybı olasılığını en aza indirdiğiniz anlamına gelir.

Yüksek oranda dinamik verileri önbelleğe alma

Hızla değişen bilgileri kalıcı bir veri deposunda depoladığınızda, bu durum sisteme ek yük getirebilir. Örneğin, sürekli durum veya başka bir ölçüm bildiren bir cihaz düşünün. Bir uygulama, önbelleğe alınan bilgilerin neredeyse her zaman eski olacağı temelinde bu verileri önbelleğe almamayı seçerse, bu bilgileri veri deposundan depolayıp alırken de aynı durum geçerli olabilir. Bu verileri kaydetmek ve getirmek için gereken süre içinde değişmiş olabilir.

Böyle bir durumda dinamik bilgileri kalıcı veri deposu yerine doğrudan önbellekte depolamanın avantajlarını göz önünde bulundurun. Veriler kritik değilse ve denetim gerekmiyorsa, zaman zaman yapılan değişikliğin kaybedilip kaybedilmesi önemli değildir.

Önbellekte veri süre sonunu yönetme

Çoğu durumda, önbellekte tutulan veriler, özgün veri deposunda tutulan verilerin bir kopyasıdır. Özgün veri deposundaki veriler önbelleğe alındıktan sonra değişebilir ve bu da önbelleğe alınan verilerin eski olmasına neden olabilir. Birçok önbelleğe alma sistemi, verilerin süresinin dolması ve verilerin güncel olma süresini kısaltmak için önbelleği yapılandırmanıza olanak tanır.

Önbelleğe alınan verilerin süresi dolduğunda önbellekten kaldırılır ve uygulamanın verileri özgün veri deposundan alması gerekir (yeni getirilen bilgileri önbelleğe geri alabilir). Önbelleği yapılandırırken varsayılan bir süre sonu ilkesi ayarlayabilirsiniz. Birçok önbellek hizmetindeki nesneleri program aracılığıyla önbellekte depoladığınızda tek tek nesneler için süre sonu da belirtebilirsiniz. Bazı önbellekler, son kullanma süresini mutlak bir değer olarak veya belirtilen süre içinde erişilmiyorsa öğenin önbellekten kaldırılmasına neden olan kayan değer olarak belirtmenizi sağlar. Bu ayar, önbellek genelindeki süre sonu ilkelerini geçersiz kılar, ancak yalnızca belirtilen nesneler için geçersiz kılar.

Note

Önbelleğin ve içerdiği nesnelerin süre sonunu dikkatle göz önünde bulundurun. Çok kısa yaparsanız, nesnelerin süresi çok hızlı dolar ve önbelleği kullanmanın avantajlarını azaltırsınız. Süreyi çok uzun yaparsanız verilerin eskime riskini alırsınız.

Verilerin uzun süre yerleşik kalmasına izin verilirse önbelleğin dolması da mümkündür. Bu durumda, önbelleğe yeni öğe ekleme istekleri, çıkarma olarak bilinen bir işlemde bazı öğelerin zorla kaldırılmasına neden olabilir. Önbellek hizmetleri genellikle verileri en son kullanılan (LRU) temelinde çıkartır, ancak genellikle bu ilkeyi geçersiz kılabilir ve öğelerin çıkarılmasını engelleyebilirsiniz. Ancak, bu yaklaşımı benimserseniz önbellekte kullanılabilen belleği aşma riskiyle karşı karşıyasınız. Önbelleğe öğe eklemeye çalışan bir uygulama bir özel durumla başarısız olur.

Bazı önbelleğe alma uygulamaları ek çıkarma ilkeleri sağlayabilir. Birkaç tür çıkarma ilkesi vardır. Bunlar şunları içerir:

  • En son kullanılan ilke (verilerin yeniden gerekli olmayacağı beklentisi ile).
  • İlk çıkan ilk ilke (en eski veriler önce çıkarılır).
  • Tetiklenen bir olayı (değiştirilen veriler gibi) temel alan açık bir kaldırma ilkesi.

İstemci tarafı önbelleğindeki verileri geçersiz kılma

İstemci tarafı önbelleğinde tutulan veriler genellikle verileri istemciye sağlayan hizmetin dışında olarak kabul edilir. Bir hizmet, istemciyi doğrudan istemci tarafı önbelleğine bilgi eklemeye veya kaldırmaya zorlayamaz.

Bu, kötü yapılandırılmış bir önbellek kullanan bir istemcinin güncel olmayan bilgileri kullanmaya devam etmesi anlamına gelir. Örneğin, önbelleğin süre sonu ilkeleri düzgün uygulanmazsa, istemci özgün veri kaynağındaki bilgiler değiştiğinde yerel olarak önbelleğe alınan eski bilgileri kullanabilir.

HTTP bağlantısı üzerinden veri sunan bir web uygulaması oluşturursanız, bir web istemcisini (tarayıcı veya web ara sunucusu gibi) en son bilgileri getirmeye örtük olarak zorlayabilirsiniz. Bir kaynağın URI'sindeki bir değişiklikle güncelleştirilirse bunu yapabilirsiniz. Web istemcileri genellikle istemci tarafı önbelleğinde anahtar olarak kaynağın URI'sini kullanır, bu nedenle URI değişirse, web istemcisi bir kaynağın önceden önbelleğe alınmış sürümlerini yoksayar ve bunun yerine yeni sürümü getirir.

Önbellekte eşzamanlılığı yönetme

Önbellekler genellikle bir uygulamanın birden çok örneği tarafından paylaşılacak şekilde tasarlanmıştır. Her uygulama örneği önbellekteki verileri okuyabilir ve değiştirebilir. Sonuç olarak, paylaşılan veri depolarında ortaya çıkan eşzamanlılık sorunları önbellek için de geçerlidir. Bir uygulamanın önbellekte tutulan verileri değiştirmesi gereken bir durumda, uygulamanın bir örneği tarafından yapılan güncelleştirmelerin başka bir örnek tarafından yapılan değişikliklerin üzerine yazılmadığından emin olmanız gerekebilir.

Verilerin doğasına ve çakışma olasılığına bağlı olarak eşzamanlılık için iki yaklaşımdan birini benimseyebilirsiniz:

  • Optimistic. Uygulama, verileri güncelleştirmeden hemen önce önbellekteki verilerin alındıktan sonra değişip değişmediğini denetler. Veriler hala aynıysa değişiklik yapılabilir. Aksi takdirde, uygulamanın uygulamayı güncelleştirip güncelleştirmeyeceğine karar vermeleri gerekir. (Bu kararı yönlendiren iş mantığı uygulamaya özgüdür.) Bu yaklaşım, güncelleştirmelerin seyrek gerçekleştiği veya çakışmaların gerçekleşme olasılığının düşük olduğu durumlar için uygundur.
  • Pessimistic. Verileri aldığında, uygulama başka bir örneğin değiştirmesini önlemek için verileri önbelleğe kilitler. Bu işlem çakışmaların oluşmamasını sağlar, ancak aynı verileri işlemesi gereken diğer örnekleri de engelleyebilir. Kötümser eşzamanlılık bir çözümün ölçeklenebilirliğini etkileyebilir ve yalnızca kısa süreli işlemler için önerilir. Bu yaklaşım, özellikle bir uygulama önbellekteki birden çok öğeyi güncelleştirdiğinde ve bu değişikliklerin tutarlı bir şekilde uygulandığından emin olması gerektiğinde çakışma olasılığının daha yüksek olduğu durumlar için uygun olabilir.

Yüksek kullanılabilirlik ve ölçeklenebilirlik uygulama ve performansı geliştirme

Birincil veri deposu olarak önbellek kullanmaktan kaçının; bu, önbelleğin dolduruldığı özgün veri deposunun rolüdür. Özgün veri deposu, verilerin kalıcılığını sağlamakla sorumludur.

Çözümlerinize paylaşılan önbellek hizmetinin kullanılabilirliği konusunda kritik bağımlılıklar eklememeye dikkat edin. Paylaşılan önbelleği sağlayan hizmet kullanılamıyorsa bir uygulamanın çalışmaya devam edebilmesi gerekir. Uygulama yanıt vermemeye başlamamalı veya önbellek hizmetinin sürdürülmesi beklenirken başarısız olmamalıdır.

Bu nedenle uygulamanın önbellek hizmetinin kullanılabilirliğini algılamaya hazır olması ve önbelleğe erişilemiyorsa özgün veri deposuna geri dönmesi gerekir. Circuit-Breaker deseni bu senaryoyu işlemek için kullanışlıdır. Önbelleği sağlayan hizmet kurtarılabilir ve hizmet kullanılabilir olduğunda, önbellek, "Cache-aside" deseni gibi bir stratejiye göre özgün veri deposundan veriler okundukça yeniden doldurulabilir.

Ancak önbellek geçici olarak kullanılamadığında uygulama özgün veri deposuna geri düşerse sistem ölçeklenebilirliği etkilenebilir. Veri deposu kurtarılırken, özgün veri deposu veri istekleriyle dolup, zaman aşımlarına ve başarısız bağlantılara neden olabilir.

Bir uygulamanın her örneğinde, tüm uygulama örneklerinin erişmiş olduğu paylaşılan önbellekle birlikte yerel, özel bir önbellek uygulamayı göz önünde bulundurun. Uygulama bir öğeyi aldığında, önce yerel önbelleğinde, ardından paylaşılan önbellekte ve son olarak özgün veri deposunda denetleyebilir. Yerel önbellek, paylaşılan önbellekteki veriler kullanılarak veya paylaşılan önbellek kullanılamıyorsa veritabanında doldurulabilir.

Bu yaklaşım, yerel önbelleğin paylaşılan önbellekle ilgili olarak çok eski olmasını önlemek için dikkatli bir yapılandırma gerektirir. Ancak, paylaşılan önbelleğe ulaşılamıyorsa yerel önbellek arabellek işlevi görür. Şekil 3'de bu yapı gösterilmektedir.

Paylaşılan önbellekle yerel özel önbellek kullanma

Şekil 3: Paylaşılan önbellekle yerel özel önbellek kullanma.

Görece uzun süreli verileri barındıran büyük önbellekleri desteklemek için bazı önbellek hizmetleri, önbellek kullanılamaz duruma gelirse otomatik yük devretme uygulayan yüksek kullanılabilirlik seçeneği sağlar. Bu yaklaşım genellikle birincil önbellek sunucusunda depolanan önbelleğe alınmış verilerin ikincil önbellek sunucusuna çoğaltılmasını ve birincil sunucu başarısız olursa veya bağlantı kesilirse ikincil sunucuya geçmeyi içerir.

Birden çok hedefe yazmayla ilişkili gecikme süresini azaltmak için, birincil sunucudaki önbelleğe veri yazıldığında ikincil sunucuya çoğaltma zaman uyumsuz olarak gerçekleşebilir. Bu yaklaşım, bir hata olduğunda önbelleğe alınan bazı bilgilerin kaybedilme olasılığına yol açar, ancak bu verilerin oranı önbelleğin genel boyutuna kıyasla küçük olmalıdır.

Paylaşılan önbellek büyükse, çekişme olasılığını azaltmak ve ölçeklenebilirliği geliştirmek için önbelleğe alınan verileri düğümler arasında bölümlemeniz yararlı olabilir. Birçok paylaşılan önbellek, düğümleri dinamik olarak ekleme (ve kaldırma) ve verileri bölümler arasında yeniden dengeleme özelliğini destekler. Bu yaklaşım, düğüm koleksiyonunun istemci uygulamalarına sorunsuz, tek bir önbellek olarak sunulduğu kümeleme içerebilir. Ancak dahili olarak veriler, yükü eşit dengeleyen önceden tanımlanmış bir dağıtım stratejisini izleyerek düğümler arasında dağıtılır. Olası bölümleme stratejileri hakkında daha fazla bilgi için bkz. Veri bölümleme kılavuzu.

Kümeleme, önbelleğin kullanılabilirliğini de artırabilir. Bir düğüm başarısız olursa önbelleğin geri kalanı hala erişilebilir durumda olur. Kümeleme, çoğaltma ve yük devretme ile birlikte sıklıkla kullanılır. Her düğüm çoğaltılabilir ve düğüm başarısız olursa çoğaltma hızlı bir şekilde çevrimiçi yapılabilir.

Birçok okuma ve yazma işlemi büyük olasılıkla tek veri değerleri veya nesneler içerir. Ancak bazen büyük hacimli verileri hızla depolamak veya almak gerekebilir. Örneğin, bir önbelleğin tohumlanması, önbelleğe yüzlerce veya binlerce öğe yazmayı içerebilir. Bir uygulamanın aynı isteğin parçası olarak önbellekten çok sayıda ilgili öğe alması da gerekebilir.

Birçok büyük ölçekli önbellek, bu amaçlar için toplu işlem sağlar. Bu, istemci uygulamasının çok büyük miktarda öğeyi tek bir istekte paketlemesini sağlar ve çok sayıda küçük istek gerçekleştirmeyle ilişkili ek yükü azaltır.

Önbelleğe alma ve nihai tutarlılık

Edilgen önbellek düzeninin çalışması için, önbelleği dolduran uygulama örneğinin verilerin en son ve tutarlı sürümüne erişimi olmalıdır. Nihai tutarlılık uygulayan bir sistemde (çoğaltılmış veri deposu gibi) bu durum söz konusu olmayabilir.

Bir uygulamanın bir örneği bir veri öğesini değiştirebilir ve bu öğenin önbelleğe alınmış sürümünü geçersiz kılabilir. Uygulamanın başka bir örneği bu öğeyi önbellekten okumaya çalışabilir ve bu da önbellekten kaçırılmasına neden olur, bu nedenle verileri veri deposundan okur ve önbelleğe ekler. Ancak, veri deposu diğer çoğaltmalarla tam olarak eşitlenmemişse, uygulama örneği önbelleği okuyabilir ve eski değerle doldurabilir.

Veri tutarlılığını işleme hakkında daha fazla bilgi için bkz. Veri tutarlılığı temel bilgileri.

Önbelleğe alınan verileri koruma

Kullandığınız önbellek hizmetinden bağımsız olarak, önbellekte tutulan verilerin yetkisiz erişime karşı nasıl korunduğunu göz önünde bulundurun. İki temel sorun vardır:

  • Önbellekteki verilerin gizliliği.
  • Önbellek ile önbelleği kullanan uygulama arasında akan verilerin gizliliği.

Önbellekteki verileri korumak için önbellek hizmeti, uygulamaların aşağıdaki ayrıntıları belirtmesini gerektiren bir kimlik doğrulama mekanizması uygulayabilir:

  • Önbellekteki verilere erişebilecek kimlikler.
  • Bu kimliklerin gerçekleştirmesine izin verilen işlemler (okuma ve yazma).

Verileri okuma ve yazma ile ilişkili ek yükü azaltmak için, bir kimliğe önbellekte yazma veya okuma erişimi verildikten sonra, bu kimlik önbellekteki tüm verileri kullanabilir.

Önbelleğe alınan verilerin alt kümelerine erişimi kısıtlamanız gerekiyorsa, aşağıdaki yaklaşımlardan birini yapabilirsiniz:

  • Önbelleği bölümlere bölün (farklı önbellek sunucuları kullanarak) ve yalnızca kullanmalarına izin verilmesi gereken bölümler için kimliklere erişim verin.
  • Farklı anahtarlar kullanarak her alt kümedeki verileri şifreleyin ve şifreleme anahtarlarını yalnızca her alt kümeye erişimi olması gereken kimliklere sağlayın. İstemci uygulaması önbellekteki tüm verileri almaya devam edebilir, ancak yalnızca anahtarların bulunduğu verilerin şifresini çözebilir.

Ayrıca, önbellekte ve önbellekten dışarı akan verileri de korumanız gerekir. Bunu yapmak için istemci uygulamalarının önbelleğe bağlanmak için kullandığı ağ altyapısı tarafından sağlanan güvenlik özelliklerine bağımlı olursunuz. Önbellek, istemci uygulamalarını barındıran aynı kuruluştaki bir şirket içi sunucu kullanılarak uygulanırsa, ağın kendisini yalıtmak için ek adımlar uygulamanız gerekmeyebilir. Önbellek uzaktan bulunuyorsa ve genel ağ üzerinden (İnternet gibi) TCP veya HTTP bağlantısı gerektiriyorsa SSL uygulamayı göz önünde bulundurun.

Azure'da önbelleğe alma uygulamayla ilgili dikkat edilmesi gerekenler

Redis için Azure Cache , bir Azure veri merkezinde hizmet olarak çalışan açık kaynak Redis önbelleğinin bir uygulamasıdır. Uygulamanın bulut hizmeti, web sitesi veya Azure sanal makinesi içinde uygulanıp uygulanmadığı, herhangi bir Azure uygulamasından erişilebilen bir önbelleğe alma hizmeti sağlar. Önbellekler, uygun erişim anahtarına sahip istemci uygulamaları tarafından paylaşılabilir.

Redis için Azure Cache kullanılabilirlik, ölçeklenebilirlik ve güvenlik sağlayan yüksek performanslı bir önbelleğe alma çözümüdür. Genellikle bir veya daha fazla ayrılmış makineye yayılmış bir hizmet olarak çalışır. Hızlı erişim sağlamak için bellekte olabildiğince çok bilgi depolamaya çalışır. Bu mimari, yavaş G/Ç işlemleri gerçekleştirme gereksinimini azaltarak düşük gecikme süresi ve yüksek aktarım hızı sağlamaya yöneliktir.

Redis için Azure Cache, istemci uygulamaları tarafından kullanılan çeşitli API'lerin çoğuyla uyumludur. Şirket içinde çalıştırılan Redis için Azure Cache'i zaten kullanan mevcut uygulamalarınız varsa, Redis için Azure Cache bulutta önbelleğe almaya yönelik hızlı bir geçiş yolu sağlar.

Redis'in Özellikleri

Redis basit bir önbellek sunucusundan daha fazlasıdır. Birçok yaygın senaryoları destekleyen kapsamlı bir komut kümesine sahip dağıtılmış bir bellek içi veritabanı sağlar. Bunlar, bu belgenin devamında Redis önbelleğe alma kullanma bölümünde açıklanmıştır. Bu bölümde Redis'in sağladığı bazı temel özellikler özetlenmiştir.

Bellek içi veritabanı olarak Redis

Redis hem okuma hem de yazma işlemlerini destekler. Redis'te yazma işlemleri, düzenli aralıklarla yerel anlık görüntü dosyasında veya yalnızca ekleme günlük dosyasında depolanarak sistem hatasına karşı korunabilir. Bu durum, geçişli veri depoları olarak kabul edilmesi gereken birçok önbellekte böyle değildir.

Tüm yazma işlemleri zaman uyumsuz olur ve istemcilerin veri okumalarını ve yazmalarını engellemez. Redis çalışmaya başladığında, anlık görüntü veya günlük dosyasındaki verileri okur ve bellek içi önbelleği oluşturmak için kullanır. Daha fazla bilgi için Redis web sitesindeki Redis kalıcılığı bölümüne bakın.

Note

Redis, yıkıcı bir hata olduğunda tüm yazmaların kaydedileceğini garanti etmez, ancak en kötü ihtimalle yalnızca birkaç saniyelik verileri kaybedebilirsiniz. Bir önbelleğin yetkili bir veri kaynağı olarak davranması amaçlanmamıştır ve kritik verilerin uygun bir veri deposuna başarıyla kaydedilmesini sağlamak için önbelleği kullanan uygulamaların sorumluluğundadır. Daha fazla bilgi için Önbellek kenarda kalma deseni konusuna bakın.

Redis veri türleri

Redis, değerlerin basit türler veya karmalar, listeler ve kümeler gibi karmaşık veri yapıları içerebildiği bir anahtar-değer deposudur. Bu veri türlerinde bir dizi atomik işlemi destekler. Anahtarlar kalıcı olabilir veya sınırlı bir yaşam süresiyle etiketlenebilir; bu noktada anahtar ve karşılık gelen değeri önbellekten otomatik olarak kaldırılır. Redis anahtarları ve değerleri hakkında daha fazla bilgi için Redis web sitesindeki Redis veri türlerine giriş ve özetler sayfasını ziyaret edin.

Redis çoğaltma ve kümeleme

Redis, kullanılabilirliği sağlamaya ve aktarım hızını korumaya yardımcı olmak için birincil/alt çoğaltmayı destekler. Redis birincil düğümüne yazma işlemleri bir veya daha fazla alt düğüme çoğaltılır. Okuma işlemleri birincil veya alt işlemlerden herhangi biri tarafından sunulur.

Bir ağ bölümünüz varsa, astlar verileri sunmaya devam edebilir ve ardından bağlantı yeniden başlatıldığında birincil bölümle saydam olarak yeniden eşitlenebilir. Diğer ayrıntılar için Redis web sitesindeki Çoğaltma sayfasını ziyaret edin.

Redis ayrıca verileri sunucular arasında saydam bir şekilde parçalara ayırmanızı ve yükü yaymanızı sağlayan kümeleme sağlar. Yeni Redis sunucuları eklenebildiği ve önbellek boyutu arttıkça verilerin yeniden bölümlenebileceği için bu özellik ölçeklenebilirliği artırır.

Ayrıca, kümedeki her sunucu birincil/alt çoğaltma kullanılarak çoğaltılabilir. Bu, kümedeki her düğümde kullanılabilirlik sağlar. Kümeleme ve parçalama hakkında daha fazla bilgi için Redis web sitesindeki Redis kümesi öğreticisi sayfasını ziyaret edin.

Redis bellek kullanımı

Redis önbelleği, konak bilgisayarda kullanılabilen kaynaklara bağlı olarak sınırlı bir boyuta sahiptir. Bir Redis sunucusunu yapılandırırken kullanabileceği en fazla bellek miktarını belirtebilirsiniz. Ayrıca, redis önbelleğindeki bir anahtarı son kullanma süresine sahip olacak şekilde yapılandırabilir ve ardından bu anahtar önbellekten otomatik olarak kaldırılır. Bu özellik, bellek içi önbelleğin eski veya eski verilerle dolmasını önlemeye yardımcı olabilir.

Bellek dolduğunda Redis, bir dizi ilkeyi izleyerek anahtarları ve değerlerini otomatik olarak çıkarabilir. Varsayılan değer LRU'dur (en son kullanılır), ancak anahtarları rastgele çıkarma veya çıkarma işlemini tamamen kapatma gibi diğer ilkeleri de seçebilirsiniz (bu durumda, önbelleğe öğe ekleme girişimi doluysa başarısız olur). Redis'i LRU önbelleği olarak kullanma sayfası daha fazla bilgi sağlar.

Redis işlemleri ve toplu işlemleri

Redis, istemci uygulamasının önbellekteki verileri atomik işlem olarak okuyan ve yazan bir dizi işlem göndermesini sağlar. İşlemdeki tüm komutların sırayla çalıştırıldığı garanti edilir ve diğer eşzamanlı istemciler tarafından verilen hiçbir komut bunlar arasında birbirine karışmaz.

Ancak bunlar ilişkisel bir veritabanı tarafından gerçekleştirileceğinden gerçek işlemler değildir. İşlem işlemi iki aşamadan oluşur: birincisi komutların kuyruğa alınıp ikincisi komutların çalıştırıldığı aşamadır. Komut kuyruğa alma aşamasında, işlemi oluşturan komutlar istemci tarafından gönderilir. Bu noktada bir tür hata oluşursa (söz dizimi hatası veya yanlış parametre sayısı gibi), Redis işlemin tamamını işlemeyi reddeder ve işlemi atar.

Çalıştırma aşamasında Redis kuyruğa alınan her komutu sırayla gerçekleştirir. Bu aşamada bir komut başarısız olursa, Redis bir sonraki kuyruğa alınan komutla devam eder ve zaten çalıştırılmış olan komutların etkilerini geri almaz. Bu basitleştirilmiş işlem biçimi, performansı korumaya ve çekişmeden kaynaklanan performans sorunlarını önlemeye yardımcı olur.

Redis, tutarlılığın korunmasına yardımcı olmak için bir iyimser kilitleme biçimi uygular. Redis ile işlemler ve kilitleme hakkında ayrıntılı bilgi için Redis web sitesindeki İşlemler sayfasını ziyaret edin.

Redis, isteklerin işlem dışı toplu işlemlerini de destekler. İstemcilerin Redis sunucusuna komut göndermek için kullandığı Redis protokolü, istemcinin aynı isteğin bir parçası olarak bir dizi işlem göndermesine olanak tanır. Bu, ağdaki paket parçalanmasını azaltmaya yardımcı olabilir. Toplu işlem işlendiğinde, her komut çalışır. Bu komutlardan herhangi biri yanlış biçimlendirilmişse reddedilir (işlemle gerçekleşmez), ancak kalan komutlar çalıştırılır. Toplu işlemdeki komutların sırası konusunda da bir garanti yoktur.

Redis güvenliği

Redis yalnızca verilere hızlı erişim sağlamaya odaklanmıştır ve yalnızca güvenilen istemciler tarafından erişilebilen güvenilir bir ortamda çalışacak şekilde tasarlanmıştır. Redis, parola kimlik doğrulamasına dayalı sınırlı bir güvenlik modelini destekler. (Bunu önermesek de kimlik doğrulamasını tamamen kaldırmak mümkündür.)

Kimliği doğrulanmış tüm istemciler aynı genel parolayı paylaşır ve aynı kaynaklara erişebilir. Daha kapsamlı oturum açma güvenliğine ihtiyacınız varsa Redis sunucusunun önünde kendi güvenlik katmanınızı uygulamanız gerekir ve tüm istemci istekleri bu ek katmandan geçmelidir. Redis'in güvenilmeyen veya kimliği doğrulanmamış istemcilere doğrudan açık olmaması gerekir.

Komutları devre dışı bırakarak veya yeniden adlandırarak (ve yalnızca yeni adlara sahip ayrıcalıklı istemciler sağlayarak) komutlara erişimi kısıtlayabilirsiniz.

Redis herhangi bir veri şifreleme biçimini doğrudan desteklemez, bu nedenle tüm kodlamanın istemci uygulamaları tarafından gerçekleştirilmesi gerekir. Ayrıca, Redis herhangi bir aktarım güvenliği sağlamaz. Ağ üzerinden akan verileri korumanız gerekiyorsa SSL proxy'si uygulamanızı öneririz.

Daha fazla bilgi için Redis web sitesindeki Redis güvenlik sayfasını ziyaret edin.

Note

Redis için Azure Cache, istemcilerin bağlandığı kendi güvenlik katmanını sağlar. Temel alınan Redis sunucuları genel ağa sunulmaz.

Azure Redis önbelleği

Redis için Azure Cache, bir Azure veri merkezinde barındırılan Redis sunucularına erişim sağlar. Erişim denetimi ve güvenlik sağlayan bir cephe görevi görür. Azure portalını kullanarak önbellek sağlayabilirsiniz.

Portal, önceden tanımlanmış bir dizi yapılandırma sağlar. Bunlar, 99%,9 hizmet düzeyi sözleşmesi (SLA) ile SSL iletişimini (gizlilik için) ve ana/alt çoğaltmayı destekleyen ayrılmış bir hizmet olarak çalışan 53 GB'lık önbellekten, paylaşılan donanımda çalıştırılan çoğaltma olmadan 250 MB önbelleğe (kullanılabilirlik garantisi yok) kadar değişir.

Azure portalını kullanarak önbelleğin çıkarma ilkesini yapılandırabilir ve sağlanan rollere kullanıcı ekleyerek önbelleğe erişimi denetleyebilirsiniz. Üyelerin gerçekleştirebileceği işlemleri tanımlayan bu roller Arasında Sahip, Katkıda Bulunan ve Okuyucu yer alır. Örneğin, Sahip rolünün üyeleri önbellek (güvenlik dahil) ve içeriği üzerinde tam denetime sahiptir, Katkıda Bulunan rolünün üyeleri önbellekteki bilgileri okuyabilir ve yazabilir ve Okuyucu rolünün üyeleri yalnızca önbellekten veri alabilir.

Yönetim görevlerinin çoğu Azure portalı üzerinden gerçekleştirilir. Bu nedenle, yapılandırmayı program aracılığıyla değiştirme, Redis sunucusunu kapatma, ek astları yapılandırma veya verileri zorla diske kaydetme gibi standart Redis sürümünde kullanılabilen yönetim komutlarının çoğu kullanılamaz.

Azure portalı, önbelleğin performansını izlemenizi sağlayan kullanışlı bir grafik ekran içerir. Örneğin, yapılan bağlantı sayısını, gerçekleştirilen istek sayısını, okuma ve yazma hacmini ve önbellek isabetlerinin önbellek isabetlerinin sayısını ve önbellek eksiklerini görüntüleyebilirsiniz. Bu bilgileri kullanarak önbelleğin verimliliğini belirleyebilir ve gerekirse farklı bir yapılandırmaya geçebilir veya çıkarma ilkesini değiştirebilirsiniz.

Ayrıca, bir veya daha fazla kritik ölçüm beklenen aralığın dışında kalırsa yöneticiye e-posta iletileri gönderen uyarılar oluşturabilirsiniz. Örneğin, önbellek eksik sayısı son bir saat içinde belirtilen değeri aşarsa yöneticiyi uyarmak isteyebilirsiniz çünkü bu, önbelleğin çok küçük olabileceği veya verilerin çok hızlı çıkarıldığı anlamına gelir.

Önbellek için CPU, bellek ve ağ kullanımını da izleyebilirsiniz.

Redis için Azure Cache oluşturmayı ve yapılandırmayı gösteren daha fazla bilgi ve örnek için Azure blogundaki Redis için Azure Cache'te tur at sayfasını ziyaret edin.

Oturum durumunu ve HTML çıkışını önbelleğe alma

Azure web rollerini kullanarak çalışan ASP.NET web uygulamaları oluşturursanız, oturum durumu bilgilerini ve HTML çıkışını Redis için Azure Cache'e kaydedebilirsiniz. Redis için Azure Cache oturum durumu sağlayıcısı, ASP.NET web uygulamasının farklı örnekleri arasında oturum bilgilerini paylaşmanıza olanak tanır ve istemci-sunucu benziminin kullanılamadığı ve bellek içindeki oturum verilerini önbelleğe almanın uygun olmadığı web grubu durumlarında çok yararlıdır.

Redis için Azure Cache ile oturum durumu sağlayıcısını kullanmak aşağıdakiler gibi çeşitli avantajlar sağlar:

  • Oturum durumunu çok sayıda ASP.NET web uygulaması örneğiyle paylaşma.
  • Geliştirilmiş ölçeklenebilirlik sağlar.
  • Birden çok okuyucu ve tek bir yazıcı için aynı oturum durumu verilerine denetimli, eşzamanlı erişimi destekleme.
  • Belleği kaydetmek ve ağ performansını geliştirmek için sıkıştırmayı kullanma.

Daha fazla bilgi için bkz. Redis için Azure Cache oturum durumu sağlayıcısı ASP.NET.

Note

Redis için Azure Cache oturum durumu sağlayıcısını Azure ortamının dışında çalışan ASP.NET uygulamalarla kullanmayın. Önbelleğe Azure dışından erişme gecikmesi, verileri önbelleğe almanın performans avantajlarını ortadan kaldırabilir.

Benzer şekilde, Redis için Azure Cache çıkış önbelleği sağlayıcısı, bir ASP.NET web uygulaması tarafından oluşturulan HTTP yanıtlarını kaydetmenizi sağlar. Çıkış önbelleği sağlayıcısını Redis için Azure Cache ile kullanmak, karmaşık HTML çıkışını işleyen uygulamaların yanıt sürelerini iyileştirebilir. Benzer yanıtlar oluşturan uygulama örnekleri, bu HTML çıkışını yeniden oluşturmak yerine önbellekteki paylaşılan çıkış parçalarını kullanabilir. Daha fazla bilgi için bkz. Redis için Azure Cache için çıkış önbelleği sağlayıcısı ASP.NET.

Özel Redis önbelleği oluşturma

Redis için Azure Cache, temel alınan Redis sunucularına yönelik bir cephe işlevi görür. Azure Redis önbelleği (53 GB'tan büyük bir önbellek gibi) kapsamında olmayan gelişmiş bir yapılandırmaya ihtiyacınız varsa, Azure Sanal Makineleri'ni kullanarak kendi Redis sunucularınızı oluşturabilir ve barındırabilirsiniz.

Bu karmaşık olabilecek bir işlemdir çünkü çoğaltma uygulamak istiyorsanız birincil ve alt düğümler olarak görev yapmak için birkaç VM oluşturmanız gerekebilir. Ayrıca, bir küme oluşturmak istiyorsanız birden çok birincil sunucuya ve alt sunucuya ihtiyacınız vardır. Yüksek düzeyde kullanılabilirlik ve ölçeklenebilirlik sağlayan en düşük kümelenmiş çoğaltma topolojisi, üç çift birincil/alt sunucu olarak düzenlenmiş en az altı VM'lerden oluşur (bir küme en az üç birincil düğüm içermelidir).

Gecikme süresini en aza indirmek için her birincil/alt çift birbirine yakın bir yerde bulunmalıdır. Bununla birlikte, önbelleğe alınmış verileri en çok kullanma olasılığı olan uygulamalara yakın bir yerde bulmak istiyorsanız, her çift kümesi farklı bölgelerde bulunan farklı Azure veri merkezlerinde çalışıyor olabilir. Azure VM olarak çalışan bir Redis düğümü oluşturma ve yapılandırma örneği için bkz. Azure'da CentOS Linux VM üzerinde Redis Çalıştırma.

Note

Kendi Redis önbelleğinizi bu şekilde uygularsanız, hizmeti izlemek, yönetmek ve güvenliğini sağlamak sizin sorumluluğunuzdadır.

Redis önbelleğini bölümleme

Önbelleği bölümleme, önbelleğin birden çok bilgisayara bölünmesini içerir. Bu yapı, tek bir önbellek sunucusu kullanmaya göre birkaç avantaj sağlar, örneğin:

  • Tek bir sunucuda depolanabilenden çok daha büyük bir önbellek oluşturma.
  • Verileri sunucular arasında dağıtarak kullanılabilirliği geliştirin. Bir sunucu başarısız olursa veya erişilemez hale gelirse, barındırdığı veriler kullanılamaz, ancak kalan sunuculardaki verilere yine erişilebilir. Önbellek için bu önemli değildir çünkü önbelleğe alınan veriler yalnızca veritabanında tutulan verilerin geçici bir kopyasıdır. Erişilemez duruma gelen bir sunucudaki önbelleğe alınan veriler bunun yerine farklı bir sunucuda önbelleğe alınabilir.
  • Yükü sunucular arasında yayarak performansı ve ölçeklenebilirliği geliştirin.
  • Verileri erişen kullanıcılara yakın bir konumda konumlandırarak gecikme süresini kısaltın.

Önbellek için en yaygın bölümleme biçimi parçalamadır. Bu stratejide, her bölüm (veya parça) kendi başına bir Redis önbelleğidir. Veriler, verileri dağıtmak için çeşitli yaklaşımlar kullanabilen parçalama mantığı kullanılarak belirli bir bölüme yönlendirilir. Parçalama deseni uygulaması hakkında daha fazla bilgi sağlar.

Redis önbelleğinde bölümleme uygulamak için aşağıdaki yaklaşımlardan birini kullanabilirsiniz:

  • Sunucu tarafı sorgu yönlendirme. Bu teknikte, istemci uygulaması önbelleği oluşturan Redis sunucularından herhangi birine (büyük olasılıkla en yakın sunucu) bir istek gönderir. Her Redis sunucusu, barındırdığı bölümü açıklayan meta verileri depolar ve ayrıca diğer sunucularda hangi bölümlerin bulunduğu hakkında bilgi içerir. Redis sunucusu istemci isteğini inceler. Yerel olarak çözümlenebiliyorsa, istenen işlemi gerçekleştirir. Aksi takdirde isteği uygun sunucuya iletir. Bu model Redis kümeleme tarafından uygulanır ve Redis web sitesindeki Redis kümesi öğretici sayfasında daha ayrıntılı olarak açıklanmıştır. Redis kümelemesi istemci uygulamaları için saydamdır ve istemcileri yeniden yapılandırmanıza gerek kalmadan kümeye ek Redis sunucuları eklenebilir (ve veriler yeniden bölümlenebilir).
  • İstemci tarafı bölümleme. Bu modelde istemci uygulaması, istekleri uygun Redis sunucusuna yönlendiren mantık (büyük olasılıkla kitaplık biçiminde) içerir. Bu yaklaşım Redis için Azure Cache ile kullanılabilir. Redis için birden çok Azure Cache (her veri bölümü için bir tane) oluşturun ve istekleri doğru önbelleğe yönlendiren istemci tarafı mantığını uygulayın. Bölümleme düzeni değişirse (örneğin, Redis için Azure Cache oluşturulduğunda), istemci uygulamalarının yeniden yapılandırılması gerekebilir.
  • Proxy destekli bölümleme. Bu düzende istemci uygulamaları, verilerin nasıl bölümlendiğini anlayan ve ardından isteği uygun Redis sunucusuna yönlendiren bir ara ara sunucu hizmetine istek gönderir. Bu yaklaşım Redis için Azure Cache ile de kullanılabilir; ara sunucu hizmeti bir Azure bulut hizmeti olarak uygulanabilir. Bu yaklaşım, hizmeti uygulamak için ek bir karmaşıklık düzeyi gerektirir ve isteklerin gerçekleştirilmesi istemci tarafı bölümleme kullanmaktan daha uzun sürebilir.

Bölümleme: Redis web sitesindeki birden çok Redis örneği arasında veri bölme sayfası, Redis ile bölümleme uygulama hakkında daha fazla bilgi sağlar.

Redis cache istemci uygulamalarını uygulama

Redis, çok sayıda programlama dilinde yazılmış istemci uygulamalarını destekler. .NET Framework kullanarak yeni uygulamalar derliyorsanız StackExchange.Redis istemci kitaplığını kullanmanızı öneririz. Bu kitaplık, Redis sunucusuna bağlanma, komut gönderme ve yanıt alma ayrıntılarını özetleyen bir .NET Framework nesne modeli sağlar. Visual Studio'da NuGet paketi olarak kullanılabilir. Redis için Azure Cache'e veya vm'de barındırılan özel bir Redis önbelleğine bağlanmak için aynı kitaplığı kullanabilirsiniz.

Redis sunucusuna bağlanmak için sınıfının statik Connect yöntemini ConnectionMultiplexer kullanırsınız. Bu yöntemin oluşturduğu bağlantı, istemci uygulamasının ömrü boyunca kullanılacak şekilde tasarlanmıştır ve aynı bağlantı birden çok eşzamanlı iş parçacığı tarafından kullanılabilir. Redis işlemini her gerçekleştirdiğinizde yeniden bağlanmayın ve bağlantıyı kesin çünkü bu işlem performansı düşürebilir.

Redis konağı adresi ve parola gibi bağlantı parametrelerini belirtebilirsiniz. Redis için Azure Cache kullanıyorsanız parola, Azure portalı kullanılarak Redis için Azure Cache için oluşturulan birincil veya ikincil anahtardır.

Redis sunucusuna bağlandıktan sonra, Redis Veritabanı'nda önbellek işlevi gören bir tanıtıcı elde edebilirsiniz. Redis bağlantısı bunu yapmak için yöntemini sağlar GetDatabase . Daha sonra ve StringGet yöntemlerini kullanarak önbellekten öğeleri alabilir ve verileri önbellekte StringSet depolayabilirsiniz. Bu yöntemler parametre olarak bir anahtar bekler ve öğeyi eşleşen bir değere () sahip olan önbellekte döndürür veya bu anahtarla (StringGetStringSet) öğeyi önbelleğe ekler.

Redis sunucusunun konumuna bağlı olarak, bir istek sunucuya iletilirken ve istemciye bir yanıt döndürülürken birçok işlem biraz gecikmeye neden olabilir. StackExchange kitaplığı, istemci uygulamalarının yanıt vermeye devam etmelerine yardımcı olmak için kullanıma sunduğu birçok yöntemin zaman uyumsuz sürümlerini sağlar. Bu yöntemler .NET Framework'teki Görev Tabanlı Zaman Uyumsuz desenini destekler.

Aşağıdaki kod parçacığı adlı RetrieveItembir yöntemi gösterir. Redis ve StackExchange kitaplığını temel alan edilgen önbellek düzeninin bir uygulamasını gösterir. yöntemi bir dize anahtarı değeri alır ve yöntemini çağırarak StringGetAsync karşılık gelen öğeyi Redis önbelleğinden almaya çalışır (zaman uyumsuz sürümü).StringGet

Öğe bulunamazsa, yöntemi kullanılarak GetItemFromDataSourceAsync temel alınan veri kaynağından getirilir (StackExchange kitaplığının parçası değil yerel bir yöntemdir). Daha sonra yöntemi kullanılarak StringSetAsync önbelleğe eklenir, böylece bir dahaki sefere daha hızlı alınabilir.

// Connect to the Azure Redis cache
ConfigurationOptions config = new ConfigurationOptions();
config.EndPoints.Add("<your DNS name>.redis.cache.windows.net");
config.Password = "<Redis cache key from management portal>";
ConnectionMultiplexer redisHostConnection = ConnectionMultiplexer.Connect(config);
IDatabase cache = redisHostConnection.GetDatabase();
...
private async Task<string> RetrieveItem(string itemKey)
{
    // Attempt to retrieve the item from the Redis cache
    string itemValue = await cache.StringGetAsync(itemKey);

    // If the value returned is null, the item was not found in the cache
    // So retrieve the item from the data source and add it to the cache
    if (itemValue == null)
    {
        itemValue = await GetItemFromDataSourceAsync(itemKey);
        await cache.StringSetAsync(itemKey, itemValue);
    }

    // Return the item
    return itemValue;
}

StringGet ve StringSet yöntemleri, dize değerlerini alma veya depolama ile sınırlı değildir. Bayt dizisi olarak seri hale getirilmiş herhangi bir öğeyi alabilirler. Bir .NET nesnesini kaydetmeniz gerekiyorsa, bayt akışı olarak seri hale getirebilirsiniz ve bunu önbelleğe yazmak için yöntemini kullanabilirsiniz StringSet .

Benzer şekilde, yöntemini kullanarak StringGet önbellekten bir nesneyi okuyabilir ve .NET nesnesi olarak seri durumdan çıkarabilirsiniz. Aşağıdaki kod, IDatabase arabirimi GetDatabase (Redis bağlantısının yöntemi bir IDatabase nesne döndürür) için bir uzantı yöntemleri kümesini ve önbellekte bir BlogPost nesneyi okumak ve yazmak için bu yöntemleri kullanan bazı örnek kodları gösterir:

public static class RedisCacheExtensions
{
    public static async Task<T> GetAsync<T>(this IDatabase cache, string key)
    {
        return Deserialize<T>(await cache.StringGetAsync(key));
    }

    public static async Task<object> GetAsync(this IDatabase cache, string key)
    {
        return Deserialize<object>(await cache.StringGetAsync(key));
    }

    public static async Task SetAsync(this IDatabase cache, string key, object value)
    {
        await cache.StringSetAsync(key, Serialize(value));
    }

    static byte[] Serialize(object o)
    {
        byte[] objectDataAsStream = null;

        if (o != null)
        {
            var jsonString = JsonSerializer.Serialize(o);
            objectDataAsStream = Encoding.ASCII.GetBytes(jsonString);
        }

        return objectDataAsStream;
    }

    static T Deserialize<T>(byte[] stream)
    {
        T result = default(T);

        if (stream != null)
        {
            var jsonString = Encoding.ASCII.GetString(stream);
            result = JsonSerializer.Deserialize<T>(jsonString);
        }

        return result;
    }
}

Aşağıdaki kod, edilgen önbellek desenini izleyerek önbelleğe seri hale getirilebilir RetrieveBlogPost bir nesne okumak ve yazmak için bu uzantı yöntemlerini kullanan adlı BlogPost bir yöntemi gösterir:

// The BlogPost type
public class BlogPost
{
    private HashSet<string> tags;

    public BlogPost(int id, string title, int score, IEnumerable<string> tags)
    {
        this.Id = id;
        this.Title = title;
        this.Score = score;
        this.tags = new HashSet<string>(tags);
    }

    public int Id { get; set; }
    public string Title { get; set; }
    public int Score { get; set; }
    public ICollection<string> Tags => this.tags;
}
...
private async Task<BlogPost> RetrieveBlogPost(string blogPostKey)
{
    BlogPost blogPost = await cache.GetAsync<BlogPost>(blogPostKey);
    if (blogPost == null)
    {
        blogPost = await GetBlogPostFromDataSourceAsync(blogPostKey);
        await cache.SetAsync(blogPostKey, blogPost);
    }

    return blogPost;
}

Redis, bir istemci uygulaması birden çok zaman uyumsuz istek gönderirse komut kanalı oluşturmayı destekler. Redis, komutları katı bir sırayla almak ve yanıtlamak yerine aynı bağlantıyı kullanarak isteklerin çoğullamasını yapabilir.

Bu yaklaşım, ağı daha verimli bir şekilde kullanarak gecikme süresini azaltmaya yardımcı olur. Aşağıdaki kod parçacığında, iki müşterinin ayrıntılarını eşzamanlı olarak alan bir örnek gösterilmektedir. Kod iki istek gönderir ve ardından sonuçları almayı beklemeden önce başka işlemler gerçekleştirir (gösterilmez). Wait Önbellek nesnesinin yöntemi .NET Framework Task.Wait yöntemine benzer:

ConnectionMultiplexer redisHostConnection = ...;
IDatabase cache = redisHostConnection.GetDatabase();
...
var task1 = cache.StringGetAsync("customer:1");
var task2 = cache.StringGetAsync("customer:2");
...
var customer1 = cache.Wait(task1);
var customer2 = cache.Wait(task2);

Redis için Azure Cache'i kullanabilen istemci uygulamaları yazma hakkında daha fazla bilgi için Redis için Azure Cache belgelerine bakın. StackExchange.Redis adresinde de daha fazla bilgi bulabilirsiniz.

Aynı web sitesindeki İşlem hatları ve çoğullayıcılar sayfası, Redis ve StackExchange kitaplığı ile zaman uyumsuz işlemler ve kanal oluşturma hakkında daha fazla bilgi sağlar.

Redis önbelleğini kullanma

Redis'in önbelleğe alma konusunda en basit kullanımı anahtar-değer çiftleridir; burada değer, herhangi bir ikili veri içerebilen rastgele uzunlukta bir kesintisiz dizedir. (Temelde dize olarak ele alınabilen bir bayt dizisidir). Bu senaryo, bu makalenin önceki bölümlerinde Redis Cache istemci uygulamalarını uygulama bölümünde gösterilmiştir.

Anahtarlar ayrıca, anahtar olarak herhangi bir ikili bilgiyi kullanabilmeniz için, bölünmemiş veriler de içerdiğini unutmayın. Ancak anahtar ne kadar uzun olursa depolamak için o kadar fazla alan gerekir ve arama işlemlerinin gerçekleştirilmesi o kadar uzun sürer. Kullanılabilirlik ve bakım kolaylığı için anahtar alanınızı dikkatlice tasarlayın ve anlamlı (ayrıntılı değil) anahtarlar kullanın.

Örneğin, yalnızca "100" yerine kimliği 100 olan müşterinin anahtarını temsil etmek için "customer:100" gibi yapılandırılmış anahtarları kullanın. Bu düzen, farklı veri türlerini depolayan değerleri kolayca ayırt etmenizi sağlar. Örneğin, kimliği 100 olan siparişin anahtarını temsil etmek için "orders:100" anahtarını da kullanabilirsiniz.

Redis anahtar-değer çiftindeki bir değer, tek boyutlu ikili dizelerin yanı sıra listeler, kümeler (sıralanmış ve sıralanmamış) ve karmalar gibi daha yapılandırılmış bilgileri de barındırabilir. Redis, bu türleri işleyebilen kapsamlı bir komut kümesi sağlar ve bu komutların çoğu StackExchange gibi bir istemci kitaplığı aracılığıyla .NET Framework uygulamalarında kullanılabilir. Redis web sitesindeki Redis veri türlerine ve özetlerine giriş sayfası, bu türlere ve bunları işlemek için kullanabileceğiniz komutlara daha ayrıntılı bir genel bakış sağlar.

Bu bölümde, bu veri türleri ve komutları için bazı yaygın kullanım örnekleri özetlenmiştir.

Atomik ve toplu işlem gerçekleştirme

Redis, dize değerleri üzerinde bir dizi atomik alma ve ayarlama işlemi destekler. Bu işlemler, ayrı GET ve SET komutlar kullanılırken oluşabilecek olası yarış tehlikelerini ortadan kaldırır. Kullanılabilir işlemler şunlardır:

  • INCR, INCRBY, DECRve DECRBY, tamsayı sayısal veri değerleri üzerinde atomik artış ve azaltma işlemleri gerçekleştirir. StackExchange kitaplığı, bu işlemleri gerçekleştirmek ve IDatabase.StringIncrementAsync önbellekte depolanan sonuç değerini döndürmek için ve yöntemlerinin aşırı yüklenmiş sürümlerini IDatabase.StringDecrementAsync sağlar. Aşağıdaki kod parçacığında bu yöntemlerin nasıl kullanılacağı gösterilmektedir:

    ConnectionMultiplexer redisHostConnection = ...;
    IDatabase cache = redisHostConnection.GetDatabase();
    ...
    await cache.StringSetAsync("data:counter", 99);
    ...
    long oldValue = await cache.StringIncrementAsync("data:counter");
    // Increment by 1 (the default)
    // oldValue should be 100
    
    long newValue = await cache.StringDecrementAsync("data:counter", 50);
    // Decrement by 50
    // newValue should be 50
    
  • GETSET, bir anahtarla ilişkili değeri alır ve yeni bir değerle değiştirir. StackExchange kitaplığı bu işlemi yöntemi aracılığıyla IDatabase.StringGetSetAsync kullanılabilir hale getirir. Aşağıdaki kod parçacığında bu yöntemin bir örneği gösterilmektedir. Bu kod, önceki örnekteki "data:counter" anahtarıyla ilişkili geçerli değeri döndürür. Ardından bu anahtarın değerini sıfıra sıfırlar ve hepsi aynı işlemin bir parçası olur:

    ConnectionMultiplexer redisHostConnection = ...;
    IDatabase cache = redisHostConnection.GetDatabase();
    ...
    string oldValue = await cache.StringGetSetAsync("data:counter", 0);
    
  • MGET ve MSET, bir dizi dize değerini tek bir işlem olarak döndürebilir veya değiştirebilir. IDatabase.StringGetAsync ve IDatabase.StringSetAsync yöntemleri, aşağıdaki örnekte gösterildiği gibi bu işlevselliği desteklemek için aşırı yüklenmiştir:

    ConnectionMultiplexer redisHostConnection = ...;
    IDatabase cache = redisHostConnection.GetDatabase();
    ...
    // Create a list of key-value pairs
    var keysAndValues =
        new List<KeyValuePair<RedisKey, RedisValue>>()
        {
            new KeyValuePair<RedisKey, RedisValue>("data:key1", "value1"),
            new KeyValuePair<RedisKey, RedisValue>("data:key99", "value2"),
            new KeyValuePair<RedisKey, RedisValue>("data:key322", "value3")
        };
    
    // Store the list of key-value pairs in the cache
    cache.StringSet(keysAndValues.ToArray());
    ...
    // Find all values that match a list of keys
    RedisKey[] keys = { "data:key1", "data:key99", "data:key322"};
    // values should contain { "value1", "value2", "value3" }
    RedisValue[] values = cache.StringGet(keys);
    
    

Ayrıca, bu makalenin başlarındaki Redis işlemleri ve toplu işlemler bölümünde açıklandığı gibi birden çok işlemi tek bir Redis işleminde birleştirebilirsiniz. StackExchange kitaplığı, arabirim aracılığıyla ITransaction işlemler için destek sağlar.

yöntemini kullanarak ITransaction bir IDatabase.CreateTransaction nesne oluşturursunuz. nesnesi tarafından ITransaction sağlanan yöntemleri kullanarak işleme komutlar çağırırsınız.

Arabirim, ITransaction tüm yöntemlerin zaman uyumsuz olması dışında, arabirim tarafından IDatabase erişilenlere benzer bir yöntem kümesine erişim sağlar. Bu, yalnızca yöntemi çağrıldığında ITransaction.Execute gerçekleştirildikleri anlamına gelir. yöntemi tarafından ITransaction.Execute döndürülen değer, işlemin başarıyla oluşturulup oluşturulmadığını (true) veya başarısız olup olmadığını (false) gösterir.

Aşağıdaki kod parçacığında, aynı işlemin parçası olarak iki sayacı artıran ve azalan bir örnek gösterilmektedir:

ConnectionMultiplexer redisHostConnection = ...;
IDatabase cache = redisHostConnection.GetDatabase();
...
ITransaction transaction = cache.CreateTransaction();
var tx1 = transaction.StringIncrementAsync("data:counter1");
var tx2 = transaction.StringDecrementAsync("data:counter2");
bool result = transaction.Execute();
Console.WriteLine("Transaction {0}", result ? "succeeded" : "failed");
Console.WriteLine("Result of increment: {0}", tx1.Result);
Console.WriteLine("Result of decrement: {0}", tx2.Result);

Redis işlemlerinin ilişkisel veritabanlarındaki işlemlerden farklı olduğunu unutmayın. Execute yöntemi yalnızca çalıştırılacak işlemi oluşturan tüm komutları kuyruğa alır ve bunlardan herhangi biri yanlış biçimlendirilmişse işlem durdurulur. Tüm komutlar başarıyla kuyruğa alındıysa, her komut zaman uyumsuz olarak çalışır.

Herhangi bir komut başarısız olursa, diğerleri işlemeye devam eder. Bir komutun başarıyla tamamlandığını doğrulamanız gerekiyorsa, önceki örnekte gösterildiği gibi ilgili görevin Result özelliğini kullanarak komutun sonuçlarını getirmeniz gerekir. Result özelliğinin okunması, görev tamamlanana kadar çağıran iş parçacığını engeller.

Daha fazla bilgi için bkz. Redis'te İşlemler.

Toplu işlem gerçekleştirirken StackExchange kitaplığının arabirimini kullanabilirsiniz IBatch . Bu arabirim, tüm yöntemlerin zaman uyumsuz olması dışında, arabirim tarafından IDatabase erişilenlere benzer bir yöntem kümesine erişim sağlar.

yöntemini kullanarak IBatch bir IDatabase.CreateBatch nesne oluşturur ve aşağıdaki örnekte gösterildiği gibi yöntemini kullanarak IBatch.Execute toplu işlemi çalıştırırsınız. Bu kod yalnızca bir dize değeri ayarlar, önceki örnekte kullanılan sayaçları artırır ve geri dönüştürür ve sonuçları görüntüler:

ConnectionMultiplexer redisHostConnection = ...;
IDatabase cache = redisHostConnection.GetDatabase();
...
IBatch batch = cache.CreateBatch();
batch.StringSetAsync("data:key1", 11);
var t1 = batch.StringIncrementAsync("data:counter1");
var t2 = batch.StringDecrementAsync("data:counter2");
batch.Execute();
Console.WriteLine("{0}", t1.Result);
Console.WriteLine("{0}", t2.Result);

İşlemin aksine, toplu işlemdeki bir komut hatalı biçimlendirilmiş olduğu için başarısız olursa diğer komutların yine de çalışabileceğini anlamak önemlidir. IBatch.Execute yöntemi herhangi bir başarı veya başarısızlık göstergesi döndürmez.

Önbellek işlemlerini tetikle ve unut

Redis, komut bayraklarını kullanarak tetikle ve unut işlemlerini destekler. Bu durumda istemci yalnızca bir işlem başlatır, ancak sonuçla ilgilenmez ve komutun tamamlanmasını beklemez. Aşağıdaki örnekte, INCR komutunun bir yangın ve unutma işlemi olarak nasıl gerçekleştirildiği gösterilmektedir:

ConnectionMultiplexer redisHostConnection = ...;
IDatabase cache = redisHostConnection.GetDatabase();
...
await cache.StringSetAsync("data:key1", 99);
...
cache.StringIncrement("data:key1", flags: CommandFlags.FireAndForget);

Otomatik olarak süresi dolan anahtarları belirtme

Bir öğeyi Redis önbelleğinde depoladığınızda, öğenin önbellekten otomatik olarak kaldırılacağı bir zaman aşımı belirtebilirsiniz. Ayrıca komutunu kullanarak TTL anahtarın süresi dolmadan önce ne kadar süre olduğunu sorgulayabilirsiniz. Bu komut, yöntemini kullanarak IDatabase.KeyTimeToLive StackExchange uygulamalarında kullanılabilir.

Aşağıdaki kod parçacığı, bir anahtarda 20 saniyelik bir süre sonu ayarlamayı ve anahtarın kalan ömrünü sorgulamayı gösterir:

ConnectionMultiplexer redisHostConnection = ...;
IDatabase cache = redisHostConnection.GetDatabase();
...
// Add a key with an expiration time of 20 seconds
await cache.StringSetAsync("data:key1", 99, TimeSpan.FromSeconds(20));
...
// Query how much time a key has left to live
// If the key has already expired, the KeyTimeToLive function returns a null
TimeSpan? expiry = cache.KeyTimeToLive("data:key1");

StackExchange kitaplığında yöntemi olarak KeyExpireAsync bulunan EXPIRE komutunu kullanarak da süre sonu süresini belirli bir tarih ve saate ayarlayabilirsiniz:

ConnectionMultiplexer redisHostConnection = ...;
IDatabase cache = redisHostConnection.GetDatabase();
...
// Add a key with an expiration date of midnight on 1st January 2015
await cache.StringSetAsync("data:key1", 99);
await cache.KeyExpireAsync("data:key1",
    new DateTime(2015, 1, 1, 0, 0, 0, DateTimeKind.Utc));
...

Tip

StackExchange kitaplığı aracılığıyla yöntem olarak IDatabase.KeyDeleteAsync kullanılabilen DEL komutunu kullanarak bir öğeyi önbellekten el ile kaldırabilirsiniz.

Önbelleğe alınmış öğeler arasında çapraz bağıntı yapmak için etiketleri kullanma

Redis kümesi, tek bir anahtarı paylaşan birden çok öğeden oluşan bir koleksiyondur. SADD komutunu kullanarak bir küme oluşturabilirsiniz. SMEMBERS komutunu kullanarak bir kümedeki öğeleri alabilirsiniz. StackExchange kitaplığı, yöntemiyle IDatabase.SetAddAsync SADD komutunu ve yöntemiyle IDatabase.SetMembersAsync SMEMBERS komutunu uygular.

Ayrıca SDIFF (set difference), SINTER (set intersection) ve SUNION (set union) komutlarını kullanarak yeni kümeler oluşturmak için mevcut kümeleri birleştirebilirsiniz. StackExchange kitaplığı bu işlemleri yönteminde bir arada sunar IDatabase.SetCombineAsync . Bu yöntemin ilk parametresi gerçekleştirilecek küme işlemini belirtir.

Aşağıdaki kod parçacıkları, kümelerin ilgili öğe koleksiyonlarını hızla depolamak ve almak için nasıl yararlı olabileceğini gösterir. Bu kod, bu makalenin BlogPost önceki bölümlerinde yer alan Redis Cache İstemci Uygulamalarını Uygulama bölümünde açıklanan türü kullanır.

Nesne BlogPost dört alan içerir: kimlik, başlık, derecelendirme puanı ve etiket koleksiyonu. İlk kod parçacığı, C# nesne listesini BlogPost doldurmada kullanılan örnek verileri gösterir:

List<string[]> tags = new List<string[]>
{
    new[] { "iot","csharp" },
    new[] { "iot","azure","csharp" },
    new[] { "csharp","git","big data" },
    new[] { "iot","git","database" },
    new[] { "database","git" },
    new[] { "csharp","database" },
    new[] { "iot" },
    new[] { "iot","database","git" },
    new[] { "azure","database","big data","git","csharp" },
    new[] { "azure" }
};

List<BlogPost> posts = new List<BlogPost>();
int blogKey = 0;
int numberOfPosts = 20;
Random random = new Random();
for (int i = 0; i < numberOfPosts; i++)
{
    blogKey++;
    posts.Add(new BlogPost(
        blogKey,                  // Blog post ID
        string.Format(CultureInfo.InvariantCulture, "Blog Post #{0}",
            blogKey),             // Blog post title
        random.Next(100, 10000),  // Ranking score
        tags[i % tags.Count]));   // Tags--assigned from a collection
                                  // in the tags list
}

Her BlogPost nesnenin etiketlerini bir Redis önbelleğinde küme olarak depolayabilir ve her kümeyi BlogPostkimliğiyle ilişkilendirebilirsiniz. Bu, uygulamanın belirli bir blog gönderisine ait tüm etiketleri hızla bulmasını sağlar. Ters yönde aramayı etkinleştirmek ve belirli bir etiketi paylaşan tüm blog gönderilerini bulmak için, anahtardaki etiket kimliğine başvuran blog gönderilerini tutan başka bir küme oluşturabilirsiniz:

ConnectionMultiplexer redisHostConnection = ...;
IDatabase cache = redisHostConnection.GetDatabase();
...
// Tags are easily represented as Redis Sets
foreach (BlogPost post in posts)
{
    string redisKey = string.Format(CultureInfo.InvariantCulture,
        "blog:posts:{0}:tags", post.Id);
    // Add tags to the blog post in Redis
    await cache.SetAddAsync(
        redisKey, post.Tags.Select(s => (RedisValue)s).ToArray());

    // Now do the inverse so we can figure out which blog posts have a given tag
    foreach (var tag in post.Tags)
    {
        await cache.SetAddAsync(string.Format(CultureInfo.InvariantCulture,
            "tag:{0}:blog:posts", tag), post.Id);
    }
}

Bu yapılar, birçok yaygın sorguyı çok verimli bir şekilde gerçekleştirmenizi sağlar. Örneğin, blog gönderisi 1'in tüm etiketlerini şu şekilde bulabilir ve görüntüleyebilirsiniz:

// Show the tags for blog post #1
foreach (var value in await cache.SetMembersAsync("blog:posts:1:tags"))
{
    Console.WriteLine(value);
}

Aşağıdaki gibi bir küme kesişim işlemi gerçekleştirerek blog gönderisi 1 ve blog gönderisi 2 için ortak olan tüm etiketleri bulabilirsiniz:

// Show the tags in common for blog posts #1 and #2
foreach (var value in await cache.SetCombineAsync(SetOperation.Intersect, new RedisKey[]
    { "blog:posts:1:tags", "blog:posts:2:tags" }))
{
    Console.WriteLine(value);
}

Ayrıca belirli bir etiket içeren tüm blog gönderilerini bulabilirsiniz:

// Show the ids of the blog posts that have the tag "iot".
foreach (var value in await cache.SetMembersAsync("tag:iot:blog:posts"))
{
    Console.WriteLine(value);
}

Son erişilen öğeleri bulma

Birçok uygulama için gereken yaygın bir görev, en son erişilen öğeleri bulmaktır. Örneğin, bir blog sitesi en son okunan blog gönderileri hakkında bilgi görüntülemek isteyebilir.

Redis listesi kullanarak bu işlevi uygulayabilirsiniz. Redis listesi, aynı anahtarı paylaşan birden çok öğe içerir. Liste, çift uçlu bir kuyruk işlevi görür. LPUSH (sol gönderme) ve RPUSH (sağ gönderme) komutlarını kullanarak öğeleri listenin herhangi bir ucuna gönderebilirsiniz. LPOP ve RPOP komutlarını kullanarak listenin herhangi bir ucundan öğe alabilirsiniz. Ayrıca, LRANGE ve RRANGE komutlarını kullanarak bir dizi öğe döndürebilirsiniz.

Aşağıdaki kod parçacıkları, StackExchange kitaplığını kullanarak bu işlemleri nasıl gerçekleştirebileceğinizi gösterir. Bu kod, BlogPost önceki örneklerden türünü kullanır. Bir blog gönderisi bir kullanıcı tarafından okundukça, IDatabase.ListLeftPushAsync yöntem blog gönderisinin başlığını Redis önbelleğindeki "blog:recent_posts" anahtarıyla ilişkili bir listeye iter.

ConnectionMultiplexer redisHostConnection = ...;
IDatabase cache = redisHostConnection.GetDatabase();
...
string redisKey = "blog:recent_posts";
BlogPost blogPost = ...; // Reference to the blog post that has just been read
await cache.ListLeftPushAsync(
    redisKey, blogPost.Title); // Push the blog post onto the list

Daha fazla blog gönderisi okundukça başlıkları aynı listeye gönderilir. Liste, başlıkların eklendiği sıraya göre sıralanır. En son okunan blog gönderileri listenin sol ucuna doğru. (Aynı blog gönderisi birden çok kez okunuyorsa, listede birden çok girdisi vardır.)

yöntemini kullanarak en son okunan gönderilerin başlıklarını IDatabase.ListRange görüntüleyebilirsiniz. Bu yöntem listeyi, başlangıç noktasını ve bitiş noktasını içeren anahtarı alır. Aşağıdaki kod, listenin en sol ucundaki 10 blog gönderisinin (0 ile 9 arasında öğeler) başlıklarını alır:

// Show latest ten posts
foreach (string postTitle in await cache.ListRangeAsync(redisKey, 0, 9))
{
    Console.WriteLine(postTitle);
}

yönteminin listeden ListRangeAsync öğe kaldırmadığını unutmayın. Bunu yapmak için ve IDatabase.ListLeftPopAsync yöntemlerini kullanabilirsinizIDatabase.ListRightPopAsync.

Listenin süresiz olarak büyümesini önlemek için, listeyi kırparak öğeleri düzenli aralıklarla kaldırabilirsiniz. Aşağıdaki kod parçacığı, listeden en çok kalan beş öğe dışında tüm öğelerin nasıl kaldırılacağını gösterir:

await cache.ListTrimAsync(redisKey, 0, 5);

Lider panosu uygulama

Varsayılan olarak, bir kümedeki öğeler belirli bir sırada tutulmaz. ZADD komutunu (StackExchange kitaplığındaki IDatabase.SortedSetAdd yöntem) kullanarak sıralı küme oluşturabilirsiniz. Öğeler, komutuna parametre olarak sağlanan puan adlı sayısal bir değer kullanılarak sıralanır.

Aşağıdaki kod parçacığı, bir blog gönderisinin başlığını sıralı listeye ekler. Bu örnekte, her blog gönderisinin, blog gönderisinin derecelendirmesini içeren bir puan alanı da vardır.

ConnectionMultiplexer redisHostConnection = ...;
IDatabase cache = redisHostConnection.GetDatabase();
...
string redisKey = "blog:post_rankings";
BlogPost blogPost = ...; // Reference to a blog post that has just been rated
await cache.SortedSetAddAsync(redisKey, blogPost.Title, blogPost.Score);

Yöntemini kullanarak blog gönderisi başlıklarını ve puanlarını artan puan sırasına IDatabase.SortedSetRangeByRankWithScores göre alabilirsiniz:

foreach (var post in await cache.SortedSetRangeByRankWithScoresAsync(redisKey))
{
    Console.WriteLine(post);
}

Note

StackExchange kitaplığı, verileri puan sırasına IDatabase.SortedSetRangeByRankAsync göre döndüren yöntemini de sağlar, ancak puanları döndürmez.

Ayrıca öğeleri azalan puan sırasına göre alabilir ve yöntemine ek parametreler IDatabase.SortedSetRangeByRankWithScoresAsync sağlayarak döndürülen öğe sayısını sınırlayabilirsiniz. Sonraki örnekte, en iyi 10 sıralanmış blog gönderisinin başlıkları ve puanları görüntülenir:

foreach (var post in await cache.SortedSetRangeByRankWithScoresAsync(
                               redisKey, 0, 9, Order.Descending))
{
    Console.WriteLine(post);
}

Sonraki örnekte, döndürülen öğeleri belirli bir puan aralığındaki öğelerle sınırlamak için kullanabileceğiniz yöntemi kullanılır IDatabase.SortedSetRangeByScoreWithScoresAsync :

// Blog posts with scores between 5000 and 100000
foreach (var post in await cache.SortedSetRangeByScoreWithScoresAsync(
                               redisKey, 5000, 100000))
{
    Console.WriteLine(post);
}

Kanalları kullanarak ileti

Redis sunucusu, veri önbelleği olarak davranmanın yanı sıra yüksek performanslı bir yayımcı/abone mekanizması aracılığıyla mesajlaşma sağlar. İstemci uygulamaları bir kanala abone olabilir ve diğer uygulamalar veya hizmetler kanala ileti yayımlayabilir. Daha sonra abone olan uygulamalar bu iletileri alabilir ve işleyebilir.

Redis, istemci uygulamalarının kanallara abone olmak için kullanması için SUBSCRIBE komutunu sağlar. Bu komut, uygulamanın iletileri kabul ettiği bir veya daha fazla kanalın adını bekler. StackExchange kitaplığı, bir .NET Framework uygulamasının ISubscription kanallara abone olmasını ve kanallarda yayımlamasını sağlayan arabirimini içerir.

Redis sunucusuna ISubscription bağlantı yöntemini kullanarak bir GetSubscriber nesne oluşturursunuz. Ardından bu nesnenin yöntemini kullanarak kanaldaki SubscribeAsync iletileri dinlersiniz. Aşağıdaki kod örneğinde "messages:blogPosts" adlı bir kanala nasıl abone olunacak gösterilmektedir:

ConnectionMultiplexer redisHostConnection = ...;
ISubscriber subscriber = redisHostConnection.GetSubscriber();
...
await subscriber.SubscribeAsync("messages:blogPosts", (channel, message) => Console.WriteLine("Title is: {0}", message));

yönteminin Subscribe ilk parametresi kanalın adıdır. Bu ad, önbellekteki anahtarlar tarafından kullanılan kuralların aynısını izler. Ad herhangi bir ikili veri içerebilir, ancak iyi bir performans ve bakım sağlamaya yardımcı olmak için nispeten kısa ve anlamlı dizeler kullanmanızı öneririz.

Ayrıca kanallar tarafından kullanılan ad alanının anahtarlar tarafından kullanılan ad alanından ayrı olduğunu unutmayın. Bu, aynı ada sahip kanallara ve anahtarlara sahip olabileceğiniz anlamına gelir, ancak bu durum uygulama kodunuzun korunmasını zorlaştırabilir.

İkinci parametre bir Eylem temsilcisidir. Bu temsilci kanalda her yeni ileti görüntülendiğinde zaman uyumsuz olarak çalışır. Bu örnekte yalnızca konsolda ileti görüntülenir (ileti blog gönderisinin başlığını içerir).

Bir kanalda yayımlamak için bir uygulama Redis PUBLISH komutunu kullanabilir. StackExchange kitaplığı bu işlemi gerçekleştirmek için yöntemini sağlar IServer.PublishAsync . Sonraki kod parçacığında "messages:blogPosts" kanalında bir iletinin nasıl yayımlanması gösterilmektedir:

ConnectionMultiplexer redisHostConnection = ...;
ISubscriber subscriber = redisHostConnection.GetSubscriber();
...
BlogPost blogPost = ...;
subscriber.PublishAsync("messages:blogPosts", blogPost.Title);

Yayımlama/abone olma mekanizması hakkında anlamanız gereken birkaç nokta vardır:

  • Birden çok abone aynı kanala abone olabilir ve hepsi bu kanalda yayımlanan iletileri alır.
  • Aboneler yalnızca abone olduktan sonra yayımlanan iletileri alır. Kanallar arabelleğe alınamaz ve bir ileti yayımlandıktan sonra Redis altyapısı iletiyi her aboneye gönderir ve ardından kaldırır.
  • Varsayılan olarak, iletiler aboneler tarafından gönderilme sırasına göre alınır. Çok fazla sayıda iletinin ve çok sayıda abonenin ve yayımcının olduğu yüksek oranda etkin bir sistemde, iletilerin sıralı teslimi garantili olarak sistemin performansını yavaşlatabilir. Her ileti bağımsızsa ve sıra önemli değilse Redis sistemi tarafından eşzamanlı işlemeyi etkinleştirebilir ve bu da yanıt hızını artırmaya yardımcı olabilir. Abone tarafından kullanılan bağlantının PreserveAsyncOrder değerini false olarak ayarlayarak bunu bir StackExchange istemcisinde gerçekleştirebilirsiniz:
ConnectionMultiplexer redisHostConnection = ...;
redisHostConnection.PreserveAsyncOrder = false;
ISubscriber subscriber = redisHostConnection.GetSubscriber();

Serileştirmeyle ilgili dikkat edilmesi gerekenler

Bir serileştirme biçimi seçtiğinizde performans, birlikte çalışabilirlik, sürüm oluşturma, mevcut sistemlerle uyumluluk, veri sıkıştırma ve bellek yükü arasındaki dengeleri göz önünde bulundurun. Performansı değerlendirirken, karşılaştırmaların bağlama son derece bağımlı olduğunu unutmayın. Bunlar gerçek iş yükünüzü yansıtmayabilir ve daha yeni kitaplıkları veya sürümleri dikkate almayabilir. Tüm senaryolar için tek bir "en hızlı" seri hale getirici yoktur.

Dikkate alınması gereken bazı seçenekler:

  • Protokol Arabellekleri (protobuf olarak da adlandırılır), Yapılandırılmış verileri verimli bir şekilde serileştirmek için Google tarafından geliştirilen bir serileştirme biçimidir. İleti yapılarını tanımlamak için kesin olarak yazılan tanım dosyalarını kullanır. Bu tanım dosyaları daha sonra iletileri seri hale getirmek ve seri durumdan çıkarma için dile özgü koda derlenir. Protobuf mevcut RPC mekanizmaları üzerinden kullanılabilir veya bir RPC hizmeti oluşturabilir.

  • Apache Thrift , serileştirme kodunu ve RPC hizmetlerini oluşturmak için kesin olarak belirlenmiş tanım dosyaları ve bir derleme adımı ile benzer bir yaklaşım kullanır.

  • Apache Avro , Protokol Arabellekleri ve Thrift'e benzer işlevler sağlar, ancak derleme adımı yoktur. Bunun yerine, serileştirilmiş veriler her zaman yapıyı açıklayan bir şema içerir.

  • JSON , insan tarafından okunabilir metin alanları kullanan açık bir standarttır. Geniş platformlar arası desteğe sahiptir. JSON ileti şemalarını kullanmaz. Metin tabanlı bir biçim olması, kablo üzerinde çok verimli değildir. Ancak bazı durumlarda önbelleğe alınmış öğeleri HTTP aracılığıyla doğrudan bir istemciye döndürebilirsiniz. Bu durumda JSON depolamak başka bir biçimden seri durumdan çıkarma ve ardından JSON'a seri hale getirme maliyetinden tasarruf edebilir.

  • ikili JSON (BSON), JSON'a benzer bir yapı kullanan ikili serileştirme biçimidir. BSON, JSON'a göre basit, kolay taranacak, seri hale getirilip seri durumdan çıkarılacak kadar hızlı olacak şekilde tasarlanmıştır. Yüklerin boyutu JSON ile karşılaştırılabilir. Verilere bağlı olarak, BSON yükü bir JSON yükünden daha küçük veya daha büyük olabilir. BSON,JSON'da bulunmayan bazı ek veri türlerine sahiptir( özellikle BinData (bayt dizileri için) ve Date.

  • MessagePack , kablo üzerinden iletim için sıkıştırılacak şekilde tasarlanmış bir ikili serileştirme biçimidir. İleti şeması veya ileti türü denetimi yok.

  • Bond , şema haline getirilmiş verilerle çalışmaya yönelik platformlar arası bir çerçevedir. Diller arası serileştirmeyi ve seri durumdan çıkarmayı destekler. Burada listelenen diğer sistemlerden önemli farklar devralma, tür diğer adları ve genel öğeler için destektir.

  • gRPC , Google tarafından geliştirilen bir açık kaynak RPC sistemidir. Varsayılan olarak, tanım dili ve temel alınan ileti değişim biçimi olarak Protokol Arabelleklerini kullanır.

Sonraki Adımlar

Aşağıdaki desenler, uygulamalarınızda önbelleğe alma uyguladığınızda senaryonuzla da ilgili olabilir:

  • Cache-aside deseni: Bu desen, isteğe bağlı olarak verilerin bir veri deposundan önbelleğe nasıl yükleneceğini açıklar. Bu düzen, önbellekte tutulan veriler ile özgün veri deposundaki veriler arasında tutarlılık sağlamaya da yardımcı olur.

  • Parçalama düzeni, büyük hacimli verileri depolarken ve bunlara erişirken ölçeklenebilirliği artırmaya yardımcı olmak için yatay bölümleme uygulama hakkında bilgi sağlar.