相親交友原始碼開發,關於分散式快取應該瞭解的一些事

雲豹科技程式設計師發表於2021-10-22

隨著網際網路的發展,使用者規模和資料規模越來越大,對相親交友原始碼的效能提出了更高的要求,快取就是其中一個非常關鍵的元件。在進行相親交友原始碼阿快取架構設計時,我們手段想到的可能就是分散式快取了。

分散式快取首先也是快取,一種效能很好但是相對稀缺的資源,和CPU快取原理基本相同,CPU是用效能更好的靜態RAM來為效能一般的DRAM加速,分散式快取則是通過記憶體或者其他高速儲存來加速,但是由於相親交友原始碼用到了分散式環境中,涉及到併發和網路的問題,所以會更加複雜一些,但是有很多方面的共性,比如快取淘汰策略。

本文包括四個部分,相親交友原始碼的分散式快取更新模式、失效機制、淘汰策略和常見問題及解決方案,重點是圍繞快取的通用原理和實現來說明。

快取的更新模式

Cache Aside模式

1、讀取失效:相親交友原始碼cache資料沒有命中,查詢DB,成功後把資料寫入快取
2、讀取命中:讀取cache資料
3、更新:把資料更新到DB,失效快取

圖示
在這裡插入圖片描述

// Read
data = cache.get(id);
if (data == null) {
    data = db.get(id);
    cache.put(id, data);
}
// Write
db.save(data);
cache.invalid(data.id);

為什麼更新不直接寫快取?

為了降低相親交友原始碼併發情況下的資料不一致發生概率(cache aside無法完全避免資料不一致,只能降低發生的概率,如果需要資料強一直可以考慮使用分散式鎖),如下圖所示

Thread-A: Write DB Version(A)
Thread-B: Write DB Version(B)
Thread-B: Write Cache Version(B)
Thread-A: Write Cache Version(A) -- 資料庫結果是B,快取裡面變成A了

這種情況下如果改為失效的話資料不一致的情況能夠避免

Thread-A: Write DB Version(A)
Thread-B: Write DB Version(B)
Thread-B: Expire Cache
Thread-A: Expire Cache -- 兩種情況只失效快取,下次讀操作會把db的最新值重新整理到快取中。

Read/Write Through模式

快取代理了DB讀取、寫入的邏輯,可以把快取看成唯一的儲存。
在這裡插入圖片描述

# [xxx] 表示一個元件
# 箭頭表示資料方向
Read:
Client <-- [Cache <-- DB]Write:Client --> [Cache --> DB]

Write Behind Caching(Write Back)模式

這種模式下相親交友原始碼所有的操作都走快取,快取裡的資料再通過非同步的方式同步到資料庫裡面。所以系統的寫效能能夠大大提升了。

在這裡插入圖片描述

快取失效策略

一般而言,相親交友原始碼快取系統中都會對快取的物件設定一個超時時間,避免浪費相對比較稀缺的快取資源。對於快取時間的處理有兩種,分別是主動失效和被動失效。

主動失效

主動失效是指相親交友原始碼系統有一個主動檢查快取是否失效的機制,比如通過定時任務或者單獨的執行緒不斷的去檢查快取佇列中的物件是否失效,如果失效就把他們清除掉,避免浪費。主動失效的好處是能夠避免記憶體的浪費,但是會佔用額外的CPU時間。

被動失效

被動失效是通過訪問快取物件的時候才去檢查快取物件是否失效,這樣的好處是相親交友原始碼系統佔用的CPU時間更少,但是風險是長期不被訪問的快取物件不會被系統清除。

快取淘汰策略

快取淘汰,又稱為快取逐出(cache replacement algorithms或者cache replacement policies),是指在相親交友原始碼儲存空間不足的情況下,快取系統主動釋放一些快取物件獲取更多的儲存空間。

對於大部分記憶體型的分散式快取(非持久化),淘汰策略優先於失效策略,一旦相親交友原始碼空間不足,快取物件即使沒有過期也會被釋放。這裡只是簡單介紹一下,相關的資料都很多,一般LRU用的比較多,可以重點了解一下。

FIFO

先進先出(First In First Out)是一種簡單的淘汰策略,相親交友原始碼快取物件以佇列的形式存在,如果空間不足,就釋放佇列頭部的(先快取)物件。一般用連結串列實現。

LRU

最近最久未使用(Least Recently Used),這種策略是根據相親交友原始碼訪問的時間先後來進行淘汰的,如果空間不足,會釋放最久沒有訪問的物件(上次訪問時間最早的物件)。比較常見的是通過優先佇列來實現。

LFU

最近最少使用(Least Frequently Used),這種策略根據相親交友原始碼最近訪問的頻率來進行淘汰,如果空間不足,會釋放最近訪問頻率最低的物件。這個演算法也是用優先佇列實現的比較常見。

分散式快取的常見問題

快取穿透

  • DB中不存在資料,每次都穿過快取查DB,造成DB的壓力。一般是網路攻擊
  • 解決方案:放入一個特殊物件(比如特定的無效物件,當然比較好的方式是使用包裝物件)

程式碼示例

# 我們先看看最簡單的青銅姿勢
value = cache.get(key)
if value is None:
    value = db.get(key)
    # 由於value為空,實際上快取並沒有寫進去,一旦這個key成為熱點,db的壓力將會極大
    cache.put(key, value, expire)
    return value
else:
    return value
# 簡單優化一下,升級成為白銀姿勢
wrapped_value = cache.get(key)
if wrapped_value is None:
    value = db.get(key)
    # 即使是空物件也通過包裝物件放到快取,當然考慮到空間還可以採用特殊值(比如-1代表不存在)的方式
    cache.put(key, wrapped_value(value), expire)
    return wrapped_value.value
else:
    return wrapped_value.value

快取擊穿

  • 在相親交友原始碼快取失效的瞬間大量請求,造成DB的壓力瞬間增大
  • 解決方案:更新快取時使用分散式鎖鎖住服務,防止請求穿透直達DB
# 白銀姿勢
wrapped_value = cache.get(key)
if wrapped_value is None:
    value = db.get(key)
    # 在寫入快取之前,大量的請求突然湧入,db瞬間被打垮
    cache.put(key, wrapped_value(value), expire)
    return wrapped_value.value
else:
    return wrapped_value.value
    
# 在白銀姿勢的基礎上我們再優化成黃金姿勢
wrapped_value = cache.get(key)
if wrapped_value is None:
    # 查db之前加一把鎖
    while wrapped_value is None:
        if try_lock(key):
            value = db.get(key)
            cache.put(key, wrapped_value(value), expire)
            return wrapped_value.value
        else:
            # 等待10毫秒之後重試
            sleep(0.01)
            wrapped_value = cache.get(key)
    return wrapped_value.value
else:
    return wrapped_value.value

快取雪崩

  • 相親交友原始碼大量快取設定了相同的失效時間,同一時間失效,造成服務瞬間效能急劇下降
  • 解決方案:快取時間使用基本時間加上隨機時間
# 通過隨機失效時間登上王者姿勢
wrapped_value = cache.get(key)
if wrapped_value is None:
    # 查db之前加一把鎖
    while wrapped_value is None:
        if try_lock(key):
            value = db.get(key)
            # 嗯,就是一個隨機失效時間,最好是在某個區間
            cache.put(key, wrapped_value(value), random_expire())
            return wrapped_value.value
        else:
            # 等待10毫秒之後重試
            sleep(0.01)
            wrapped_value = cache.get(key)
    return wrapped_value.value
else:
    return wrapped_value.value

以上便是“相親交友原始碼快取架構設計,分散式快取的那些事”的全部內容,希望對大家開發相親交友原始碼有幫助。

本文轉載自網路,轉載僅為分享乾貨知識,如有侵權歡迎聯絡雲豹科技進行刪除處理
原文連結:https://blog.csdn.net/u011320646/article/details/85491103


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69996194/viewspace-2838820/,如需轉載,請註明出處,否則將追究法律責任。

相關文章