Redis常見問題

2021-10-24 03:12:17 字數 3610 閱讀 7640

在專案使用redis,主要是考慮效能和併發。

專案中我們碰到需要執行很久的並且結果不頻繁變動的查詢時,就可以將結果集放在redis快取中,之後的請求就會到快取中讀取,沒有所需結果再去資料庫查詢。極大的提高了效能,使得請求能夠迅速響應。

在併發性比較高的情況所有的請求直接訪問資料庫可能會導致資料庫連線異常,利用redis快取,使得請求先訪問redis,不直接訪問資料庫。

string

string是redis最基本的型別,乙個key對應乙個value。string型別是二進位制安全的。意思是redis的string可以包含任何資料,value只最多是512m。常規set/get操作,對應的值可以是string也可以是數字。一般做一些計數功能的快取、手機驗證碼快取

@test

public void teststring()

// 刪除

"username");

}

hash

存放的值是物件,比較方便操作物件的屬性字段。在做單點登入時,以cookieid為key,值可以用這種資料結構儲存使用者相關資訊,設定對應過期時間可以做出類似session過期的效果。

@test

public void testhash()

// 獲取 hash 型別所有的資料

mapusermap = jedis.hgetall("userinfo");

for (map.entryuserinfo : usermap.entryset())

// 刪除 用於刪除 hash 型別資料

"userinfo", "name");

}

list

使用 list 的資料結構,可以做簡單的訊息佇列的功能;另外,可以利用 lrange 命令,做基於 redis 的分頁功能,效能極佳,使用者體驗好。

@test

public void testlist()

// 獲取總條數

long total = jedis.llen("students");

system.out.println("總條數:" + total);

// 刪除單條 刪除列表中第一次出現的 li si

// jedis.lrem("students", 1, "li si");

// 刪除多條

// jedis.del("students");

}

set

因為 set 堆放的是一堆不重複值的集合,所以可以做全域性去重的功能。

@test

public void testset()

// 刪除

"letters", "aaa", "bbb");

}

sorted set

sorted set 多了乙個權重引數 score,集合中的元素能夠按 score 進行排列,可以做排行榜應用,取 top n 操作,sorted set 可以用來做延時任務。

@test

public void testsortedset()

// 獲取總條數

long total = jedis.zcard("score");

system.out.println("總條數:" + total);

// 刪除

"score", "zhangsan", "lisi");

}

redis 採用的是定期刪除+惰性刪除策略。

為什麼不用定時刪除策略

定期刪除+惰性刪除如何工作

定期刪除,redis 預設每個 100ms 檢查,有過期 key 則刪除。需要說明的是,redis 不是每個 100ms 將所有的 key 檢查一次,而是隨機抽取進行檢查。如果只採用定期刪除策略,會導致很多 key 到時間沒有刪除。於是,惰性刪除派上用場。

採用定期刪除+惰性刪除就沒其他問題了麼

這樣,redis 的記憶體會越來越高,那麼就應該採用記憶體淘汰機制。

在 redis.conf 中有一行配置:

#maxmemory-policy volatile-lru

該配置就是配記憶體淘汰策略的:

一致性問題還可以再分為最終一致性和強一致性。資料庫和快取雙寫,就必然會存在不一致的問題,前提是如果對資料有強一致性要求,不能放快取,我們所做的一切,只能保證最終一致性。

另外,我們所做的方案從根本上來說,只能降低不一致發生的概率,因此,有強一致性要求的資料,不能放快取。首先,採取正確更新策略,先更新資料庫,再刪快取;其次,因為可能存在刪除快取失敗的問題,提供乙個補償措施即可,例如利用訊息佇列。

這兩個問題,一般中小型傳統軟體企業很難碰到。如果有大併發的專案,流量有幾百萬左右,這兩個問題一定要深刻考慮。快取穿透,即黑客故意去請求快取中不存在的資料,導致所有的請求都懟到資料庫上,從而資料庫連線異常。

1.利用互斥鎖,快取失效的時候,先去獲得鎖,得到鎖了,再去請求資料庫。沒得到鎖,則休眠一段時間重試。

2.採用非同步更新策略,無論 key 是否取到值,都直接返回。value 值中維護乙個快取失效時間,快取如果過期,非同步起乙個執行緒去讀資料庫,更新快取。需要做快取預熱(專案啟動前,先載入快取)操作。

3.提供乙個能迅速判斷請求是否有效的攔截機制,比如,利用布隆過濾器,內部維護一系列合法有效的 key。迅速判斷出,請求所攜帶的 key 是否合法有效。如果不合法,則直接返回。

快取雪崩,即快取同一時間大面積的失效,這個時候又來了一波請求,結果請求都懟到資料庫上,從而導致資料庫連線異常。

1.給快取的失效時間,加上乙個隨機值,避免集體失效。

2.使用互斥鎖,但是該方案吞吐量明顯下降了。

3.雙快取。我們有兩個快取,快取 a 和快取 b。快取 a 的失效時間為 20 分鐘,快取 b 不設失效時間,自己做快取預熱操作。

4.然後細分以下幾個小點:從快取 a 讀資料庫,有則直接返回;a 沒有資料,直接從 b 讀資料,直接返回,並且非同步啟動乙個更新執行緒,更新執行緒同時更新快取 a 和快取 b。

但是我並不推薦使用 redis 的事務機制。因為我們的生產環境,基本都是 redis 集群環境,做了資料分片操作。你乙個事務中有涉及到多個 key 操作的時候,這多個 key 不一定都儲存在同乙個 redis-server 上。因此,redis 的事務機制,十分雞肋。

如果對這個 key 操作,不要求順序

這種情況下,準備乙個分布式鎖,大家去搶鎖,搶到鎖就做 set 操作即可,比較簡單。

如果對這個 key 操作,要求順序

假設有乙個 key1,系統 a 需要將 key1 設定為 valuea,系統 b 需要將 key1 設定為 valueb,系統 c 需要將 key1 設定為 valuec。

期望按照 key1 的 value 值按照 valuea > valueb > valuec 的順序變化。這種時候我們在資料寫入資料庫的時候,需要儲存乙個時間戳。

假設時間戳如下:

系統 a key 1

系統 b key 1

系統 c key 1

那麼,假設系統 b 先搶到鎖,將 key1 設定為。接下來系統 a 搶到鎖,發現自己的 valuea 的時間戳早於快取中的時間戳,那就不做 set 操作了,以此類推。其他方法,比如利用佇列,將 set 方法變成序列訪問也可以。

合理利用redis。

redis常見問題

在redis命令列執行info clients 得到類似下面的結果 connected clients 357 client longest output list 0client biggest input buf 0blocked clients 0redis連線數過多的問題可以參考 處理red...

redis常見問題

redis使用中可能出現的一些問題 1.快取穿透 快取穿透是指查詢乙個一定不存在的資料,由於快取是不命中時需要從db查詢,查不到資料則不寫入快取,這將導致這個不存在的資料每次請求都要到資料庫查詢,從而造成快取穿透。解決辦法 持久層查詢不到就快取空結果,查詢時先判斷快取中是否exists key 如果...

Redis常見問題

1.如何解決快取雪崩?2.如何解決快取穿透?3.如何保證快取與資料庫雙寫時一致的問題?1.1 什麼是快取雪崩?回顧一下我們為什麼要用快取 redis 現在有個問題,如果我們的快取掛掉了,這意味著我們的全部請求都跑去資料庫了。我們都知道redis不可能把所有的資料都快取起來 記憶體昂貴且有限 所以re...