新聞中心
重建緩存——利用Redis最新的過(guò)期緩存特性

創(chuàng)新互聯(lián)致力于互聯(lián)網(wǎng)網(wǎng)站建設(shè)與網(wǎng)站營(yíng)銷,提供網(wǎng)站制作、網(wǎng)站建設(shè)、網(wǎng)站開(kāi)發(fā)、seo優(yōu)化、網(wǎng)站排名、互聯(lián)網(wǎng)營(yíng)銷、微信小程序開(kāi)發(fā)、公眾號(hào)商城、等建站開(kāi)發(fā),創(chuàng)新互聯(lián)網(wǎng)站建設(shè)策劃專家,為不同類型的客戶提供良好的互聯(lián)網(wǎng)應(yīng)用定制解決方案,幫助客戶在新的全球化互聯(lián)網(wǎng)環(huán)境中保持優(yōu)勢(shì)。
Redis是一種高性能的內(nèi)存數(shù)據(jù)庫(kù),廣泛應(yīng)用于緩存、消息隊(duì)列、排行榜、實(shí)時(shí)計(jì)數(shù)、分布式鎖等場(chǎng)合。而緩存是Redis最為常見(jiàn)的應(yīng)用場(chǎng)景之一,通過(guò)緩存可以將經(jīng)常被查詢的數(shù)據(jù)存儲(chǔ)在內(nèi)存中,從而提升應(yīng)用的性能。
然而,緩存也存在一些問(wèn)題,比如緩存的數(shù)據(jù)一旦過(guò)期,就需要重新查詢數(shù)據(jù)庫(kù)生成新的緩存。在高并發(fā)場(chǎng)景下,如果大量的請(qǐng)求到達(dá),同時(shí)緩存失效,就可能導(dǎo)致數(shù)據(jù)庫(kù)承受巨大的壓力,甚至宕機(jī)。因此,如何高效地重建緩存,成為了緩存設(shè)計(jì)的一大難點(diǎn)。
最新版本的Redis引入了一種新的特性——過(guò)期緩存,通過(guò)這個(gè)特性,可以讓Redis在緩存過(guò)期時(shí),異步地執(zhí)行一些操作,比如查詢數(shù)據(jù)庫(kù),生成新的緩存。具體來(lái)說(shuō),當(dāng)緩存過(guò)期后,Redis會(huì)將請(qǐng)求放入一個(gè)專門的隊(duì)列中,然后由后臺(tái)線程異步執(zhí)行請(qǐng)求,生成新的緩存,最后再將新的緩存寫(xiě)回Redis中。
下面,我們來(lái)看一下如何實(shí)現(xiàn)基于Redis的過(guò)期緩存特性,來(lái)高效地重建緩存。
我們需要在Redis中設(shè)置過(guò)期時(shí)間:
redis.set(KEY, value, ex=3600) # 設(shè)置過(guò)期時(shí)間為1小時(shí)
接下來(lái),定義一個(gè)裝飾器函數(shù),用于生成新的緩存:
import threading
def refresh_cache(redis, key, func):
def wrapper(*args, **kwargs):
value = redis.get(key)
if value is None:
lock_key = key + ':lock'
locked = redis.set(lock_key, 1, nx=True, ex=10)
if locked:
value = func(*args, **kwargs)
redis.set(key, value, ex=3600)
redis.delete(lock_key)
else:
value = redis.get(key)
return value
def expired_callback(key):
func_args = key.decode().split(':')[:-1]
threading.Thread(target=wrapper, args=func_args).start()
redis.config_set('notify-keyspace-events', 'Ex') # 讓Redis監(jiān)聽(tīng)過(guò)期事件
keyspace_notifications = redis.pubsub(ignore_subscribe_messages=True)
keyspace_notifications.psubscribe('__key*__:expired')
keyspace_notifications.run_in_thread(sleep_time=0.001, daemon=True, callback=expired_callback)
return wrapper
裝飾器函數(shù)接收三個(gè)參數(shù),分別是Redis對(duì)象、緩存的鍵和一個(gè)生成新緩存的函數(shù)。當(dāng)請(qǐng)求到達(dá)時(shí),裝飾器函數(shù)首先嘗試從Redis中獲取相應(yīng)的緩存,如果緩存已過(guò)期,則加鎖,防止多個(gè)請(qǐng)求同時(shí)生成新緩存,然后再次嘗試獲取緩存,如果依然為None,則調(diào)用生成新緩存的函數(shù),并將新的緩存寫(xiě)回Redis中。最后釋放鎖,并返回緩存的值。
當(dāng)緩存過(guò)期后,裝飾器函數(shù)使用Redis的“監(jiān)聽(tīng)過(guò)期事件”功能,來(lái)異步執(zhí)行生成新緩存的操作。它首先設(shè)置Redis的配置選項(xiàng),讓Redis監(jiān)聽(tīng)過(guò)期事件。然后,使用Redis的發(fā)布/訂閱功能,訂閱鍵空間的“過(guò)期事件”,并指定回調(diào)函數(shù)為expired_callback。這個(gè)回調(diào)函數(shù)會(huì)在過(guò)期事件發(fā)生時(shí)被調(diào)用,并將過(guò)期的鍵作為參數(shù)傳入。在回調(diào)函數(shù)中,我們通過(guò)過(guò)期的鍵,獲取到生成新緩存的函數(shù)和相應(yīng)的參數(shù),在新的線程中執(zhí)行這個(gè)函數(shù),生成新的緩存,并將它寫(xiě)入Redis中。
我們可以在需要使用緩存的函數(shù)上使用裝飾器函數(shù),實(shí)現(xiàn)緩存的高效重建:
@refresh_cache(redis, 'my_cache_key', generate_cache)
def query_from_cache():
# 從緩存中查詢數(shù)據(jù)
pass
基于Redis的過(guò)期緩存特性,可以讓我們?cè)诰彺媸Ш?,高效地重建緩存,避免?duì)數(shù)據(jù)庫(kù)造成不必要的壓力,同時(shí)也可以提升應(yīng)用性能。
香港服務(wù)器選創(chuàng)新互聯(lián),2H2G首月10元開(kāi)通。
創(chuàng)新互聯(lián)(www.cdcxhl.com)互聯(lián)網(wǎng)服務(wù)提供商,擁有超過(guò)10年的服務(wù)器租用、服務(wù)器托管、云服務(wù)器、虛擬主機(jī)、網(wǎng)站系統(tǒng)開(kāi)發(fā)經(jīng)驗(yàn)。專業(yè)提供云主機(jī)、虛擬主機(jī)、域名注冊(cè)、VPS主機(jī)、云服務(wù)器、香港云服務(wù)器、免備案服務(wù)器等。
當(dāng)前文章:重建緩存利用Redis最新的過(guò)期緩存特性(redis緩存過(guò)期6)
本文路徑:http://www.fisionsoft.com.cn/article/cdiheej.html


咨詢
建站咨詢
