成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

面試題:什么是緩存擊穿、緩存穿透和緩存雪崩?它們分別會帶來什么危害?該如何解決和預防?

開發
緩存穿透是指查詢一個一定不存在的數據,由于緩存是不命中時需要從數據庫查詢,查不到數據則不寫入緩存,這將導致這個不存在的數據每次請求都要到數據庫去查詢,造成緩存穿透。

一、面試官:請說說看什么是緩存擊穿,他會帶來什么危害,以及該如何解決?

1.緩存擊穿

(1) 定義:緩存擊穿是指在高并發訪問下,某個熱點數據的緩存過期失效,而此時恰好有大量并發請求訪問該數據,導致這些請求直接繞過緩存,訪問后端數據庫或存儲系統,使數據庫或存儲系統負載急劇增加,甚至可能引發系統崩潰的現象。

(2) 危害:

  • 數據庫壓力增大:大量請求直接訪問數據庫,可能導致數據庫負載過高,響應時間延長,甚至引發數據庫崩潰。
  • 系統性能下降:由于數據庫處理請求的速度遠低于緩存,因此緩存擊穿會導致系統整體性能下降。

(3) 解決方案:

① 互斥鎖(Mutex)和分布式鎖(在分布式系統中):

在緩存失效時,使用互斥鎖機制確保只有一個請求能夠訪問數據庫并更新緩存,其他請求則等待鎖釋放后從緩存中獲取數據。

下面是一個使用 Redis 分布式鎖和 Redis 事務來解決緩存擊穿問題的具體代碼示例(Python實現)。


import redis
import time
import uuid

# 連接到 Redis 服務器
redis_client = redis.StrictRedis(host='localhost', port=6379, db=0)

# 設置分布式鎖的鍵和過期時間(秒)
LOCK_KEY = 'cache_擊穿_lock'
LOCK_EXPIRE = 10  # 鎖的有效期,可以根據需要調整

# 緩存的鍵和值(示例)
CACHE_KEY = 'some_hot_data'

def acquire_lock(redis_client, lock_key, lock_value, expire):
    """
    嘗試獲取分布式鎖
    :param redis_client: Redis 客戶端
    :param lock_key: 鎖的鍵
    :param lock_value: 鎖的值(通常是唯一標識符)
    :param expire: 鎖的過期時間(秒)
    :return: 是否成功獲取鎖
    """
    while True:
        # 嘗試設置鎖,NX 表示只有鍵不存在時才設置,PX 表示過期時間(毫秒)
        result = redis_client.set(lock_key, lock_value, nx=True, px=expire * 1000)
        if result:
            return True
        # 休眠一小段時間后重試,避免忙等待
        time.sleep(0.01)

def release_lock(redis_client, lock_key, lock_value):
    """
    釋放分布式鎖
    :param redis_client: Redis 客戶端
    :param lock_key: 鎖的鍵
    :param lock_value: 鎖的值(必須是獲取鎖時使用的相同值)
    :return: 是否成功釋放鎖
    """
    # 使用 Lua 腳本確保原子性釋放鎖
    lua_script = """
    if redis.call("get", KEYS[1]) == ARGV[1] then
        return redis.call("del", KEYS[1])
    else
        return 0
    end
    """
    redis_client.eval(lua_script, 1, lock_key, lock_value)
    return True

def get_data_with_cache_and_lock(redis_client, cache_key):
    """
    使用緩存、分布式鎖和 Redis 事務獲取數據
    :param redis_client: Redis 客戶端
    :param cache_key: 緩存的鍵
    :return: 數據值或 None(如果數據不存在)
    """
    # 嘗試從緩存中獲取數據
    cache_value = redis_client.get(cache_key)
    if cache_value is not None:
        return cache_value.decode('utf-8')  # 假設數據是字符串類型

    # 嘗試獲取分布式鎖
    lock_value = str(uuid.uuid4())
    if acquire_lock(redis_client, LOCK_KEY, lock_value, LOCK_EXPIRE):
        try:
            # 使用 Redis 事務確保原子性
            pipe = redis_client.pipeline(True)
            try:
                # 嘗試再次從緩存中獲取數據(防止其他客戶端在獲取鎖后更新了緩存)
                pipe.watch(cache_key)
                cache_value = pipe.get(cache_key)
                if cache_value is not None:
                    pipe.unwatch()
                    pipe.reset()
                    return cache_value.decode('utf-8')

                # 從數據庫中獲取數據(模擬)
                # 在實際應用中,這里應該是訪問數據庫的邏輯
                data_from_db = "data_from_db"  # 假設從數據庫中獲取的數據

                # 更新緩存
                pipe.multi()
                pipe.set(cache_key, data_from_db)
                pipe.execute()

                # 返回從數據庫中獲取的數據
                return data_from_db

            except redis.WatchError:
                # 如果在事務執行過程中,緩存被其他客戶端更新,則重新嘗試獲取數據
                pass

        finally:
            # 釋放鎖
            release_lock(redis_client, LOCK_KEY, lock_value)

    # 如果無法獲取鎖或緩存仍然為空,則返回 None(或根據業務邏輯返回默認值)
    return None

# 示例調用
data = get_data_with_cache_and_lock(redis_client, CACHE_KEY)
print(f"獲取的數據: {data}")

② 熱點數據永不過期:

對于重要的熱點數據,可以設置其永不過期,以避免緩存過期引發的擊穿問題。

但需要注意數據更新時的及時性和準確性,以及可能帶來的內存占用問題。

③ 提前異步刷新緩存:

在緩存即將過期之前,通過定時任務或后臺線程提前異步加載緩存數據,確保在緩存失效之前已經有新的數據加載到緩存中。

二、面試官:再說說看什么是緩存穿透,如何檢測是否存在緩存穿透,以及該如何解決?

緩存穿透是指查詢一個一定不存在的數據,由于緩存是不命中時需要從數據庫查詢,查不到數據則不寫入緩存,這將導致這個不存在的數據每次請求都要到數據庫去查詢,造成緩存穿透。

如果數據庫查詢不到這條數據,則不會寫入緩存,這將導致這個不存在的數據每次請求都會去查詢數據庫,對數據庫造成很大的壓力。

緩存穿透通常是由惡意用戶或攻擊者請求不存在于緩存和后端存儲中的數據來發起的攻擊。

一般來說,緩存穿透一開始會由開發者發現系統接口變慢或監控告警發覺,再檢測系統日志證實。檢查數據庫訪問日志和緩存訪問日志,查看是否存在大量對不存在的鍵的查詢。這些查詢如果頻繁發生,那么很可能是緩存穿透。

另外,監控緩存的命中率。如果命中率突然下降,且伴隨著數據庫訪問量的增加,這可能是緩存穿透的征兆。

再者,可以分析系統接收到的請求參數,特別是那些明顯不符合業務邏輯的非法參數。

以下是兩種防止緩存穿透的策略:

1.布隆過濾器(Bloom Filter)

布隆過濾器是一種空間效率很高的數據結構,它利用多個哈希函數來將一個元素映射到一個位數組的多個位中。當查詢一個元素時,它會檢查對應的位是否都為1,如果是,則認為元素可能存在(注意是可能存在,因為存在哈希沖突的情況),否則認為元素一定不存在。

在緩存穿透的場景中,可以在查詢緩存之前先使用布隆過濾器檢查元素是否存在。如果布隆過濾器認為元素不存在,則直接返回一個錯誤信息或默認值,而不去查詢數據庫。這樣可以有效減少對數據庫的無效查詢。

布隆過濾器的缺點:

  • 誤判率:布隆過濾器通過多個哈希函數將元素映射到位數組中,因此存在哈希沖突的可能性。這意味著,當查詢一個元素時,布隆過濾器可能會誤判該元素存在(即位數組中對應的位都為1),而實際上該元素在數據庫中并不存在。雖然誤判率可以通過增加哈希函數數量和位數組長度來降低,但這也會增加計算復雜度和空間開銷。
  • 刪除困難:布隆過濾器不支持直接刪除元素。如果要從布隆過濾器中刪除一個元素,需要將其對應的所有位都重置為0。然而,這可能會影響其他元素的判斷,因為多個元素可能共享同一個位。因此,在實際應用中,布隆過濾器通常用于只讀場景或需要頻繁查詢但很少更新的場景。

2.空值緩存(并不推薦):

對于那些查詢結果為空的數據,也將其緩存起來,但設置一個較短的過期時間。這樣,當下次再次查詢這個不存在的數據時,可以直接從緩存中獲取空值,而不是去查詢數據庫。

控制緩存的缺點:

  • 額外的內存消耗:當數據庫中不存在某個數據時,系統仍然需要將其作為一個空值(或特殊標記)緩存起來。這會導致緩存中存儲大量的空值或特殊標記,從而占用額外的內存空間。如果這類空值數據過多,會顯著影響緩存的存儲效率和性能。
  • 數據不一致性:空值緩存的過期時間需要合理設置。如果過期時間設置得過長,當數據庫中實際數據發生變化(例如,原本不存在的數據被插入)時,緩存中的空值數據仍然有效,這會導致數據不一致的問題。相反,如果過期時間設置得過短,可能會頻繁觸發緩存失效和數據庫查詢,增加系統負擔。
  • 難以維護:空值緩存需要額外的邏輯來處理過期時間和數據更新等問題。這增加了系統的復雜性和維護成本。同時,由于空值數據在緩存中的存在,也可能導致緩存污染和命中率下降等問題。

三、面試官:什么是緩存雪崩,緩存雪崩產生的常見原因有哪些?

緩存雪崩是指在分布式系統中,緩存中的大量數據同時失效或過期,導致大量請求直接訪問數據庫或后端服務,造成系統性能急劇下降甚至癱瘓的現象。

這種現象通常會對系統造成災難性的影響,因為它會導致后端數據庫或服務承受巨大的壓力,可能引發服務不可用或數據丟失等問題。

雪崩和擊穿、熱key的問題不太?樣的是,他是指?規模的緩存都過期失效了。

緩存雪崩產生的常見原因主要包括以下幾點:

  • 緩存中大量key同時過期:如果系統中存在大量緩存數據的過期時間被設置為相同或相近,那么當這些緩存數據同時過期時,系統將無法從緩存中獲取數據,轉而直接訪問數據庫。這將導致數據庫承受巨大的訪問壓力,可能引發性能下降或崩潰。
  • 緩存服務器故障:緩存服務器作為系統中的關鍵組件,如果發生故障或宕機,將導致緩存數據無法被訪問。此時,系統同樣會轉向直接訪問數據庫,從而引發緩存雪崩。
  • 系統壓力增大:在高并發或大規模用戶訪問的情況下,系統壓力會急劇增大。如果此時緩存無法有效承載這些請求,或者緩存的命中率顯著下降,那么大量請求將直接落到數據庫上,從而引發緩存雪崩。

為了預防緩存雪崩的發生,可以采取以下措施:

  • 避免大量key同時過期:可以通過微調key的過期時間,使其有一定的相差間隔,從而避免大量key同時過期的場景。
  • 使用緩存降級策略:在緩存失效或訪問壓力過大的情況下,可以啟動降級策略,如返回默認值或錯誤信息,以減少對后端系統的壓力。
  • 緩存預熱:在系統啟動時,提前將部分或全部熱點數據加載到緩存中。
  • 后備緩存:使用二級緩存(如本地緩存)作為后備,當主緩存失效時,可以從后備緩存中獲取數據。
責任編輯:趙寧寧 來源: 程序員阿沛
相關推薦

2019-11-05 14:24:31

緩存雪崩框架

2020-09-14 06:57:30

緩存穿透雪崩

2021-06-05 09:01:01

Redis緩存雪崩緩存穿透

2020-12-28 12:37:36

緩存擊穿穿透

2023-03-10 13:33:00

緩存穿透緩存擊穿緩存雪崩

2019-10-12 14:19:05

Redis數據庫緩存

2022-03-08 00:07:51

緩存雪崩數據庫

2021-12-25 22:28:27

緩存穿透緩存擊穿緩存雪崩

2023-11-10 14:58:03

2020-03-16 14:57:24

Redis面試雪崩

2024-03-12 10:44:42

2022-05-27 07:57:20

緩存穿透緩存雪崩緩存擊穿

2020-10-23 10:46:03

緩存雪崩擊穿

2023-12-06 13:38:00

Redis緩存穿透緩存擊穿

2022-11-18 14:34:28

2020-03-05 09:09:18

緩存原因方案

2023-04-14 07:34:19

2018-12-13 12:43:07

Redis緩存穿透

2025-05-28 02:25:00

高并發緩存穿透雪崩

2020-10-13 07:44:40

緩存雪崩 穿透
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产乱码高清区二区三区在线 | 国产农村一级国产农村 | 日韩精品成人一区二区三区视频 | 久久婷婷香蕉热狠狠综合 | 国产福利视频网站 | 亚洲国产精品一区二区久久 | 亚洲伊人久久综合 | 亚洲精品一二三 | 久久免费精品 | 黄视频在线网站 | 日本一区二区三区免费观看 | 亚洲图片视频一区 | 成人av免费 | 国产69久久精品成人看动漫 | 6080yy精品一区二区三区 | 免费看黄色小视频 | 成人片免费看 | 国产精品不卡 | 一级黄色片在线免费观看 | 国产精品久久久久久久久久免费 | 国产伦精品一区二区三区在线 | 国产精品久久久久久久久久妞妞 | 二区精品| 午夜免费福利电影 | 成人在线小视频 | 1204国产成人精品视频 | 污污的网站在线观看 | 久久一 | 欧美极品在线视频 | 欧美成人h版在线观看 | 在线观看国产视频 | 精品粉嫩aⅴ一区二区三区四区 | 久久乐国产精品 | 欧美成人a| 精品毛片 | 国产精品久久久久久久久久久久久 | 中文字幕动漫成人 | 精品欧美一区二区精品久久久 | 99精品久久久久 | 精品一区二区三区在线观看国产 | 亚洲女人的天堂 |