摘要:實(shí)際執(zhí)行緩存操作的函數(shù)需要用到數(shù)據(jù)行的延遲值,如果某個(gè)數(shù)據(jù)行的延遲值不存在,那么程序?qū)⑷∠麑?duì)這個(gè)數(shù)據(jù)行的調(diào)度。上一篇文章實(shí)戰(zhàn)第二章使用構(gòu)建應(yīng)用第三節(jié)網(wǎng)頁緩存下一篇文章實(shí)戰(zhàn)第二章使用構(gòu)建應(yīng)用第五節(jié)網(wǎng)頁分析
上一篇文章: Python--Redis實(shí)戰(zhàn):第二章:使用Redis構(gòu)建Web應(yīng)用:第三節(jié):網(wǎng)頁緩存
下一篇文章:Python--Redis實(shí)戰(zhàn):第二章:使用Redis構(gòu)建Web應(yīng)用:第五節(jié):網(wǎng)頁分析
到目前為止,我們已經(jīng):
將原本由關(guān)系數(shù)據(jù)庫(kù)和網(wǎng)頁瀏覽器實(shí)現(xiàn)的登錄和訪客會(huì)話轉(zhuǎn)移到了Redis上面實(shí)現(xiàn);
將原本有關(guān)系數(shù)據(jù)庫(kù)實(shí)現(xiàn)的購(gòu)物車也放到了Redis上面實(shí)現(xiàn);
將所有頁面緩存到了Redis里面;
這一系列工作提升了網(wǎng)站的性能,降低了關(guān)系數(shù)據(jù)庫(kù)的負(fù)載并較少了網(wǎng)站的成本。
現(xiàn)在經(jīng)過分析,我們的網(wǎng)站的商品頁面通常只會(huì)從數(shù)據(jù)庫(kù)里面載入一兩行數(shù)據(jù),包括已登錄用戶的用戶信息【這些信息可以通過AJAX動(dòng)態(tài)載入,所以不會(huì)對(duì)頁面緩存造成影響】和商品本身的信息。即使是那些無法被整個(gè)緩存起來的頁面:比如用戶賬號(hào)頁面、記錄用戶以往購(gòu)買商品的頁面等等,程序也可以通過緩存頁面載入時(shí)所需的數(shù)據(jù)庫(kù)行來減少載入頁面所需的時(shí)間。
為了展示數(shù)據(jù)行緩存的作用,我們假設(shè)我們的網(wǎng)站為了清空舊庫(kù)存和吸引客戶消費(fèi),決定開始新一輪的促銷活動(dòng):這個(gè)活動(dòng)每天都會(huì)推出一些特價(jià)商品供用戶搶購(gòu),所有特價(jià)商品的數(shù)量都是限定的,賣完即止。在這種情況下,網(wǎng)址是不能對(duì)整個(gè)促銷頁面進(jìn)行緩存的,因?yàn)檫@可能會(huì)導(dǎo)致用戶看到錯(cuò)誤的特價(jià)商品的剩余數(shù)量,但是每次載入頁面都從數(shù)據(jù)庫(kù)里面取出特價(jià)商品的剩余數(shù)量的話,又會(huì)給數(shù)據(jù)庫(kù)帶來巨大的壓力,并導(dǎo)致我們需要花費(fèi)額外的成本來擴(kuò)展數(shù)據(jù)庫(kù)。
為了應(yīng)對(duì)促銷互動(dòng)帶來的大量負(fù)載,我們需要對(duì)數(shù)據(jù)行進(jìn)行緩存,具體的做法是:編寫一個(gè)持續(xù)運(yùn)行的守護(hù)進(jìn)程函數(shù),讓這個(gè)函數(shù)將指定的數(shù)據(jù)行緩存到Redis里面,并不定期地對(duì)這些緩存進(jìn)行更新。緩存函數(shù)會(huì)將數(shù)據(jù)行編碼【encode】為JSON字典并存儲(chǔ)在Redis的字符串里面,其中,數(shù)據(jù)列【column】的名字會(huì)被映射為JSON字典的鍵,而數(shù)據(jù)行的值則會(huì)被映射為JSON字典的值。
程序使用了兩個(gè)有序集合來記錄應(yīng)該在何時(shí)對(duì)緩存進(jìn)行更新:
第一個(gè)有序集合為調(diào)度【schedule】有序集合,它的成員為數(shù)據(jù)行的行ID,而分值則是一個(gè)時(shí)間戳,這個(gè)時(shí)間戳記錄了應(yīng)該在何時(shí)將制定的數(shù)據(jù)行緩存到Redus里面
第二個(gè)有序集合為延時(shí)【delay】有序集合,它的成員也是數(shù)據(jù)行的ID,而分值則記錄了指定數(shù)據(jù)行的緩存需要每隔多少秒更新一次。
為了讓緩存函數(shù)定期的緩存數(shù)據(jù)行,程序首先需要將行ID和給定的延遲值添加到延遲有序集合里面,然后再將行ID和當(dāng)前時(shí)間的時(shí)間戳添加到調(diào)度有序集合里面。實(shí)際執(zhí)行緩存操作的函數(shù)需要用到數(shù)據(jù)行的延遲值,如果某個(gè)數(shù)據(jù)行的延遲值不存在,那么程序?qū)⑷∠麑?duì)這個(gè)數(shù)據(jù)行的調(diào)度。如果我們想要移除某個(gè)數(shù)據(jù)行已有的緩存,并且讓緩存函數(shù)不再緩存那個(gè)數(shù)據(jù)行,那么只需要把那個(gè)數(shù)據(jù)行的延遲值設(shè)置為小于或等于0就可以了。
#負(fù)責(zé)調(diào)度緩存和終止緩存的函數(shù) import time def schedule_row_cache(conn,row_id,delay): #先設(shè)置數(shù)據(jù)行的延遲值 conn.zadd("delay:",row_id,delay) #立即對(duì)需要緩存的數(shù)據(jù)行進(jìn)行調(diào)度 conn.zadd("schedule:",row_id,time.time())
現(xiàn)在我們已經(jīng)完成了調(diào)度部分,那么接下來該如何對(duì)數(shù)據(jù)進(jìn)行緩存呢?負(fù)責(zé)緩存數(shù)據(jù)行的函數(shù)會(huì)嘗試讀取調(diào)度有序集合的第一個(gè)元素以及該元素的分值,如果調(diào)度有序集合沒有包含任何元素,或者分值存儲(chǔ)的時(shí)間戳所指定的時(shí)間尚未來臨,那么函數(shù)會(huì)先休眠50毫秒,然后再重新進(jìn)行檢查。當(dāng)緩存函數(shù)發(fā)現(xiàn)了一個(gè)需要理解進(jìn)行更新的數(shù)據(jù)行時(shí),緩存函數(shù)會(huì)檢查這個(gè)數(shù)據(jù)行的延遲值:如果數(shù)據(jù)行的延遲值小于或者等于0,那么緩存函數(shù)會(huì)從延遲有序集合和調(diào)度有序集合里面移除這個(gè)數(shù)據(jù)行ID,并從緩存里面刪除這個(gè)數(shù)據(jù)行已有的緩存,然后再重新進(jìn)行檢查;對(duì)于延遲值大于0的數(shù)據(jù)行來說,緩存函數(shù)會(huì)中數(shù)據(jù)庫(kù)里面取出這些行,將他們編碼為JSON格式并存儲(chǔ)到Redis里面,然后更新這些行的調(diào)度時(shí)間。
def cahce_rows(conn): while not QUIT: #嘗試獲取下一個(gè)需要被緩存的數(shù)據(jù)行以及該行的調(diào)度時(shí)間戳,命令會(huì)返回一個(gè)包含0或1個(gè)元祖【tuple】的列表 next=conn.zrange("schedule:",0,0,withscores=True) now=time.time() if not next or next[0][3]>now: #暫時(shí)沒有行需要被緩存,休眠50毫秒后重試 time.sleep(.05) continue row_id=next[0][0] #獲取下一次調(diào)度的延遲水岸 delay=conn.zscore("delay:",row_id) if delay<=0: #不必再緩存這個(gè)行,將他從緩存中移除 conn.zrem("delay:",row_id) conn.delete("inv:"+row_id) continue #讀取行數(shù)據(jù) row=Inventory.get(row_id) #更新調(diào)度時(shí)間并設(shè)置緩存值 conn.zadd("schedule:",row_id,now+delay) conn.set("inv:"+row_id,json.dumps(row.to_dict()))
通過組合使用調(diào)度函數(shù)和持續(xù)運(yùn)行緩存函數(shù),我們實(shí)現(xiàn)了一種重復(fù)進(jìn)行調(diào)度的自動(dòng)緩存機(jī)制,并且可以隨心所欲地控制緩存行緩存的更新頻率:如果數(shù)據(jù)行記錄的是特價(jià)促銷商品的剩余數(shù)量,并且參與促銷活動(dòng)的用戶非常多的話,那么我們最好每隔幾秒更新一次數(shù)據(jù)行緩存;另一方面,如果數(shù)據(jù)并不經(jīng)常改變,或者商品缺貨是可以接受的,那么我們可以每分鐘更新一次緩存。
在這一節(jié)中,我們學(xué)習(xí)了如何將數(shù)據(jù)行緩存到Redis里面,在下面一節(jié)中,我們通過只緩存一部分頁面來減少時(shí)間頁面緩存所需的內(nèi)存數(shù)量。
上一篇文章: Python--Redis實(shí)戰(zhàn):第二章:使用Redis構(gòu)建Web應(yīng)用:第三節(jié):網(wǎng)頁緩存
下一篇文章:Python--Redis實(shí)戰(zhàn):第二章:使用Redis構(gòu)建Web應(yīng)用:第五節(jié):網(wǎng)頁分析
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/42562.html
摘要:研究表明,減少用戶等待頁面載入的時(shí)間,可以增加用戶使用網(wǎng)站的欲望,并改善用戶對(duì)網(wǎng)站的印象。上一篇文章實(shí)戰(zhàn)第二章使用構(gòu)建應(yīng)用第二節(jié)使用實(shí)現(xiàn)購(gòu)物車下一篇文章實(shí)戰(zhàn)第二章使用構(gòu)建應(yīng)用第四節(jié)數(shù)據(jù)行緩存 上一篇文章: Python--Redis實(shí)戰(zhàn):第二章:使用Redis構(gòu)建Web應(yīng)用:第二節(jié):使用Redis實(shí)現(xiàn)購(gòu)物車下一篇文章:Python--Redis實(shí)戰(zhàn):第二章:使用Redis構(gòu)建Web應(yīng)用...
摘要:每個(gè)分值,函數(shù)就會(huì)刪除所有排名在名之后的商品,并將刪除之后剩余的所有商品的瀏覽次數(shù)減半。上一篇文章實(shí)戰(zhàn)第二章使用構(gòu)建應(yīng)用第四節(jié)數(shù)據(jù)行緩存下一篇文章實(shí)戰(zhàn)第三章命令第一節(jié)字符串 上一篇文章:Python--Redis實(shí)戰(zhàn):第二章:使用Redis構(gòu)建Web應(yīng)用:第四節(jié):數(shù)據(jù)行緩存下一篇文章:Python--Redis實(shí)戰(zhàn):第三章:Redis命令:第一節(jié):字符串 網(wǎng)站可以從用戶的訪問、交互、...
閱讀 2182·2021-10-12 10:11
閱讀 870·2021-10-09 09:41
閱讀 3807·2021-09-09 11:37
閱讀 1977·2021-09-08 10:41
閱讀 2664·2019-08-30 12:58
閱讀 2392·2019-08-30 10:58
閱讀 1309·2019-08-26 13:40
閱讀 4174·2019-08-26 13:36