問題原因
小編負責的應用是一個管理後台應用,權限管理使用 Shiro 框架,由於存在多個節點,需要使用分散式 Session,於是這裡使用 Redis 儲存 Session 資訊。
由於 Shiro 並沒有直接提供 Redis 儲存 Session 元件,阿粉不得不使用 Github 一個開源元件 shiro-redis。
由於 Shiro 框架需要定期驗證 Session 是否有效,因此 Shiro 底層將會呼叫 SessionDAO#getActiveSessions
取得所有的 Session 資訊。
而shiro-redis
剛好繼承SessionDAO
這個接口,底層使用用keys
指令來尋找Redis 所有儲存的Session
key。
public Set<byte> keys(byte[] pattern){ checkAndInit(); Set<byte> keys = null; Jedis jedis = jedisPool.getResource(); try{ keys = jedis.keys(pattern); }finally{ jedis.close(); } return keys; }</byte></byte>
找到問題原因,解決方法就比較簡單了,github 上查找到解決方案,升級一下 shiro-redis
到最新版本。
在這個版本,shiro-redis
採用 scan
指令取代 keys
,從而修正這個問題。
public Set<byte> keys(byte[] pattern) { Set<byte> keys = null; Jedis jedis = jedisPool.getResource(); try{ keys = new HashSet<byte>(); ScanParams params = new ScanParams(); params.count(count); params.match(pattern); byte[] cursor = ScanParams.SCAN_POINTER_START_BINARY; ScanResult<byte> scanResult; do{ scanResult = jedis.scan(cursor,params); keys.addAll(scanResult.getResult()); cursor = scanResult.getCursorAsBytes(); }while(scanResult.getStringCursor().compareTo(ScanParams.SCAN_POINTER_START) > 0); }finally{ jedis.close(); } return keys; }</byte></byte></byte></byte>
雖然問題成功解決了,但阿粉心裡還是有點不解。
為什麼keys
指令會導致其他指令執行變慢?
為什麼Keys
指令查詢會這麼慢?
為什麼Scan
指令就沒有問題?
Redis 執行指令的原理
首先我們來看第一個問題,為什麼keys
指令會導致其他指令執行變慢?
站在客戶端的視角,執行一條指令分成三步驟:
發送指令
執行指令
返回結果
但是這僅僅是客戶端自己以為的過程,但是實際上同一時刻,可能存在很多客戶端發送命令給Redis ,而Redis 我們都知道它採用的是單線程模型。
為了處理同一時刻所有的客戶端的請求命令,Redis 內部採用了佇列的方式,排隊執行。
於是客戶端執行一條指令實際上需要四個步驟:
發送指令
指令排隊
- 執行指令
- 傳回結果
#由於Redis 單執行緒執行指令,只能依序從佇列取出任務開始執行。
只要 3 這個流程執行指令速度過慢,佇列其他任務不得不進行等待,這對外部客戶端看來,Redis 好像就被阻塞一樣,一直無法回應。
所以使用 Redis 程序切勿執行需要長時間運行的指令,這可能導致 Redis 阻塞,影響執行其他指令。
KEYS 原理接下來開始回答第二個問題,為什麼
指令查詢會這麼慢?
回答這個問題之前,請先回想 Redis 底層儲存結構。
不太清楚朋友的也沒關係,大家可以回看一下之前的文章「阿里面試官:HashMap 熟悉吧?好的,那就來聊聊 Redis 字典吧!」。 keys
指令需要回傳所有的符合給定模式pattern
的 Redis 中鍵,為了實現這個目的,Redis 不得不遍歷字典中ht[ 0]哈希表底層數組,這個時間複雜度為
(N 為Redis 中key 所有的數量)。
即使 Redis 中的鍵數量很少,它仍然會有很快的執行速度。當Redis鍵的數量逐漸增多,達到百萬、千萬,甚至上億級時,它的執行速度會變得非常緩慢。 下面是阿粉本地做的一次實驗,使用lua 腳本往Redis 中增加10W 個key,然後使用
查詢所有鍵,這個查詢大概會阻塞十幾秒的時間。這裡阿粉使用 Docker 部署 Redis,效能可能會稍差。eval "for i=1,100000 do redis.call('set',i,i+1) end" 0
SCAN 原理最後我們來看下第三個問題,為什麼
指令就沒有問題? 這是因為 scan指令採用一種黑科技-
。 每次呼叫
指令,Redis 都會向使用者傳回一個新的遊標以及一定數量的 key。下次再想繼續取得剩餘的 key,需要將這個遊標傳入 scan 指令, 以此來延續先前的迭代過程。 簡單來講,
指令使用分頁查詢 redis 。
下面是一個scan 指令的迭代過程範例:
指令使用遊標這個方式,巧妙將一次全量查詢拆分成多次,降低查詢複雜度。 雖然
scan
指令時間複雜度與keys一樣,都是「O(N)」
,但由於
指令只需要回傳少量的key,所以執行速度會很快。 最後,雖然
scan
指令解決
- 不足,但同時也引入其他一些缺陷:
- ###同一個元素可能會被回傳多次,這需要我們應用程式增加處理重複元素功能。 ###
在迭代過程中,有可能會傳回正在增加到 Redis 的元素,或是正在被刪除的元素,也有可能不會。
以上這些缺陷,在我們開發中需要考慮這種情況。
除了scan
以外,redis 還有其他幾個用於增量迭代命令:
sscan
:用於迭代目前資料庫中的資料庫鍵,用於解決smembers
可能產生阻塞問題hscan
指令用於迭代雜湊鍵中的鍵值對,用於解決hgetall
可能產生阻塞問題。zscan
:指令用於迭代有序集合中的元素(包括元素成員和元素分數),用於產生zrange
#可能產生阻塞問題。
以上是Redis指令使用實例分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

Redis和SQL數據庫的主要區別在於:Redis是內存數據庫,適用於高性能和靈活性需求;SQL數據庫是關係型數據庫,適用於復雜查詢和數據一致性需求。具體來說,1)Redis提供高速數據訪問和緩存服務,支持多種數據類型,適用於緩存和實時數據處理;2)SQL數據庫通過表格結構管理數據,支持複雜查詢和事務處理,適用於電商和金融系統等需要數據一致性的場景。

REDISACTSASBOTHADATASTOREANDASERVICE.1)ASADATASTORE,ITUSESIN-MEMORYSTOOGATOFORFOFFASTESITION,支持VariousDatharptructuresLikeKey-valuepairsandsortedsetsetsetsetsetsetsets.2)asaservice,ItprovidespunctionslikeItionitionslikepunikeLikePublikePublikePlikePlikePlikeAndluikeAndluAascriptingiationsmpleplepleclexplectiations

Redis與其他數據庫相比,具有以下獨特優勢:1)速度極快,讀寫操作通常在微秒級別;2)支持豐富的數據結構和操作;3)靈活的使用場景,如緩存、計數器和發布訂閱。選擇Redis還是其他數據庫需根據具體需求和場景,Redis在高性能、低延遲應用中表現出色。

Redis在數據存儲和管理中扮演著關鍵角色,通過其多種數據結構和持久化機製成為現代應用的核心。 1)Redis支持字符串、列表、集合、有序集合和哈希表等數據結構,適用於緩存和復雜業務邏輯。 2)通過RDB和AOF兩種持久化方式,Redis確保數據的可靠存儲和快速恢復。

Redis是一種NoSQL數據庫,適用於大規模數據的高效存儲和訪問。 1.Redis是開源的內存數據結構存儲系統,支持多種數據結構。 2.它提供極快的讀寫速度,適合緩存、會話管理等。 3.Redis支持持久化,通過RDB和AOF方式確保數據安全。 4.使用示例包括基本的鍵值對操作和高級的集合去重功能。 5.常見錯誤包括連接問題、數據類型不匹配和內存溢出,需注意調試。 6.性能優化建議包括選擇合適的數據結構和設置內存淘汰策略。

Redis在現實世界中的應用包括:1.作為緩存系統加速數據庫查詢,2.存儲Web應用的會話數據,3.實現實時排行榜,4.作為消息隊列簡化消息傳遞。 Redis的多功能性和高性能使其在這些場景中大放異彩。

Redis脫穎而出是因為其高速、多功能性和豐富的數據結構。 1)Redis支持字符串、列表、集合、散列和有序集合等數據結構。 2)它通過內存存儲數據,支持RDB和AOF持久化。 3)從Redis6.0開始引入多線程處理I/O操作,提升了高並發場景下的性能。

RedisisclassifiedasaNoSQLdatabasebecauseitusesakey-valuedatamodelinsteadofthetraditionalrelationaldatabasemodel.Itoffersspeedandflexibility,makingitidealforreal-timeapplicationsandcaching,butitmaynotbesuitableforscenariosrequiringstrictdataintegrityo


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能

Dreamweaver Mac版
視覺化網頁開發工具

記事本++7.3.1
好用且免費的程式碼編輯器

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

Dreamweaver CS6
視覺化網頁開發工具