白云網(wǎng)站制作視頻運(yùn)營管理平臺(tái)
問題列表
- 為什么選擇 spring boot 框架,它與 Spring 有什么區(qū)別?
- spring mvc 的執(zhí)行流程是什么?
- 如何實(shí)現(xiàn) spring 的 IOC 過程,會(huì)用到什么技術(shù)?
- spring boot 的自動(dòng)化配置的原理是什么?
- 如何理解 spring boot 中的 star?
- spring boot 為什么要用嵌入式的 web 容器?
- 利用 REDIS 存儲(chǔ)數(shù)據(jù)的原則是什么?
- 如果 dB 的數(shù)據(jù)發(fā)生變更,如何更新緩存內(nèi)的數(shù)據(jù)?
- 如果流量很大,REDIS 掛了會(huì)發(fā)生什么,采取的措施是什么,有什么兜底的方案?
- 造成 REDIS 掛掉的原因有哪些?
- 什么是數(shù)據(jù)的傾斜,如何預(yù)防數(shù)據(jù)的傾斜?
- REDIS6.0 的多線程是怎樣的?
- 有沒有遇到過 REDIS 突然變慢的情況,原因是什么?
- REDIS 的內(nèi)存碎片是怎么造成的?
- REDIS 是如何支持原子操作的?
- 在訂單每天都是百萬級(jí)別的數(shù)據(jù)量且超過 30 分鐘未支付系統(tǒng)自動(dòng)取消訂單的場(chǎng)景下,如何設(shè)計(jì)把訂單的狀態(tài)改為取消?
- 訂單系統(tǒng)中 MQ 的具體使用場(chǎng)景是什么?
- 如何保證 MQ 消息的冪等?
- rocket mq 是如何保證消息不丟失的?有沒有做過相關(guān)設(shè)置?
- 微服務(wù)拆分的原則是什么?
- 微服務(wù)中分布式事務(wù)的具體解決的方案是什么?采用的 Seata 是用的哪種模式,其執(zhí)行過程是什么?這種模式下的隔離級(jí)別和 MYSQL 的隔離級(jí)別有什么不一樣,會(huì)不會(huì)有什么問題,如何解決?
- 公司的 SQL 語句規(guī)范是什么?表在建立索引的時(shí)候有什么原則?
- 為什么不建議用 uuid 作為 MYSQL 的主鍵索引?
- select 語句的查詢過程是什么,如何預(yù)防回表?
- 在線上給一個(gè)小表加了個(gè)字段結(jié)果導(dǎo)致整個(gè)庫都掛了,原因是什么,如何解決?
- MYSQL 中是如何出現(xiàn)死鎖的,在設(shè)計(jì)表的時(shí)候如何減少鎖的沖突?
- 單點(diǎn)登錄系統(tǒng)是用什么協(xié)議來實(shí)現(xiàn)的?如何解決 token 或 session 的跨域問題?
- 如何設(shè)計(jì)和實(shí)現(xiàn)微信掃碼登錄的功能?
面試題答案
Spring相關(guān)
- 為什么選擇Spring Boot框架,它與Spring有什么區(qū)別
- 選擇原因:快速構(gòu)建項(xiàng)目,簡(jiǎn)化配置,有大量starter依賴,自動(dòng)配置減少開發(fā)工作量,內(nèi)置服務(wù)器便于部署和運(yùn)行。
- 區(qū)別:Spring是一個(gè)框架體系,需大量配置;Spring Boot基于Spring,以約定大于配置為核心,簡(jiǎn)化配置,更易上手和快速開發(fā)。
- Spring MVC的執(zhí)行流程
- 用戶發(fā)送請(qǐng)求到DispatcherServlet。
- DispatcherServlet查詢HandlerMapping找到對(duì)應(yīng)的Handler。
- 調(diào)用HandlerAdapter執(zhí)行Handler。
- Handler執(zhí)行完成返回ModelAndView給DispatcherServlet。
- DispatcherServlet通過ViewResolver解析視圖并渲染,將結(jié)果返回給用戶。
- 如何實(shí)現(xiàn)Spring的IOC過程,會(huì)用到什么技術(shù)
- 實(shí)現(xiàn)方式:通過配置文件或注解定義Bean,Spring容器負(fù)責(zé)創(chuàng)建和管理Bean。
- 技術(shù):反射用于創(chuàng)建對(duì)象,依賴注入通過構(gòu)造函數(shù)、Setter方法等實(shí)現(xiàn)。
- Spring Boot的自動(dòng)化配置的原理
- 基于條件注解,根據(jù)類路徑下是否存在某些類、Bean等條件,決定是否自動(dòng)配置某個(gè)功能。通過@ConfigurationProperties綁定配置屬性,EnableAutoConfiguration開啟自動(dòng)配置,讀取META-INF/spring.factories文件中的自動(dòng)配置類進(jìn)行加載和配置。
- 如何理解Spring Boot中的starter
- Starter是一組依賴描述符,將相關(guān)的依賴和配置整合在一起。用戶只需引入starter依賴,Spring Boot就能自動(dòng)配置相關(guān)功能,簡(jiǎn)化依賴管理和配置,如spring-boot-starter-web引入后可快速搭建Web項(xiàng)目。
- Spring Boot為什么要用嵌入式的web容器
- 便于快速部署和運(yùn)行,無需單獨(dú)安裝和配置外部Web容器??蓪?yīng)用打包成可執(zhí)行的jar或war文件,直接運(yùn)行,提高開發(fā)和部署效率,便于在不同環(huán)境中快速遷移和部署。
Redis相關(guān)
-
利用REDIS存儲(chǔ)數(shù)據(jù)的原則是什么
- 數(shù)據(jù)讀寫頻繁、對(duì)讀寫速度要求高的適合存Redis。如緩存熱點(diǎn)數(shù)據(jù)、實(shí)時(shí)統(tǒng)計(jì)數(shù)據(jù)、分布式鎖等。要考慮數(shù)據(jù)的生命周期,合理設(shè)置過期時(shí)間,避免內(nèi)存占用過多。
-
如果DB的數(shù)據(jù)發(fā)生變更,如何更新緩存內(nèi)的數(shù)據(jù)
- 采用緩存更新策略,有先更新數(shù)據(jù)庫再更新緩存、先刪除緩存再更新數(shù)據(jù)庫、先更新數(shù)據(jù)庫再異步刪除緩存等方式。根據(jù)業(yè)務(wù)場(chǎng)景選擇合適策略,注意數(shù)據(jù)一致性問題。
-
如果流量很大,REDIS掛了會(huì)發(fā)生什么,采取的措施是什么,有什么兜底的方案
- 發(fā)生情況:緩存失效,大量請(qǐng)求直接訪問數(shù)據(jù)庫,可能導(dǎo)致數(shù)據(jù)庫壓力過大甚至崩潰,系統(tǒng)響應(yīng)變慢,部分業(yè)務(wù)可能無法正常處理。
- 措施:采用Redis集群,增加節(jié)點(diǎn)提高可靠性和性能;開啟持久化,保證數(shù)據(jù)不丟失。
- 兜底方案:使用本地緩存做臨時(shí)過渡,對(duì)數(shù)據(jù)庫進(jìn)行限流、降級(jí)等操作,保證核心業(yè)務(wù)可用。
-
造成REDIS掛掉的原因有哪些
- 內(nèi)存不足,超出最大內(nèi)存限制。網(wǎng)絡(luò)故障,節(jié)點(diǎn)之間通信異常。大量請(qǐng)求導(dǎo)致CPU使用率過高。持久化出現(xiàn)問題,如磁盤空間滿等。軟件或硬件故障等。
-
什么是數(shù)據(jù)的傾斜,如何預(yù)防數(shù)據(jù)的傾斜
- 定義:數(shù)據(jù)在Redis集群節(jié)點(diǎn)中分布不均勻,部分節(jié)點(diǎn)數(shù)據(jù)量過大,部分節(jié)點(diǎn)數(shù)據(jù)量很少,導(dǎo)致負(fù)載不均衡。
- 預(yù)防:合理設(shè)計(jì)數(shù)據(jù)分片策略,采用一致性哈希等算法。對(duì)數(shù)據(jù)進(jìn)行預(yù)處理,將數(shù)據(jù)均勻分布。監(jiān)控?cái)?shù)據(jù)分布情況,及時(shí)調(diào)整。
-
REDIS6.0的多線程是怎樣的
- Redis 6.0引入多線程主要用于網(wǎng)絡(luò)I/O讀寫,提高網(wǎng)絡(luò)讀寫性能。多線程負(fù)責(zé)讀取請(qǐng)求、解析命令、發(fā)送響應(yīng)等操作,數(shù)據(jù)處理仍由單線程執(zhí)行,避免了多線程數(shù)據(jù)競(jìng)爭(zhēng)問題,通過配置參數(shù)可調(diào)整線程數(shù)量等。
-
有沒有遇到過REDIS突然變慢的情況,原因是什么
- 內(nèi)存不足,觸發(fā)內(nèi)存淘汰策略,導(dǎo)致數(shù)據(jù)讀寫變慢。有大量復(fù)雜的慢查詢命令,阻塞了Redis線程。網(wǎng)絡(luò)帶寬不足或網(wǎng)絡(luò)延遲高。持久化操作頻繁,影響了讀寫性能。CPU負(fù)載過高,忙于處理其他任務(wù)。
-
REDIS的內(nèi)存碎片是怎么造成的
- 內(nèi)存分配器分配和釋放內(nèi)存時(shí),由于分配的內(nèi)存塊大小和實(shí)際使用的內(nèi)存大小不一致,多次分配和釋放后就會(huì)產(chǎn)生內(nèi)存碎片。例如,頻繁地創(chuàng)建和刪除不同大小的鍵值對(duì),會(huì)導(dǎo)致內(nèi)存空間不連續(xù),形成碎片。
-
REDIS是如何支持原子操作的
- Redis通過單線程和命令隊(duì)列來實(shí)現(xiàn)原子操作。單線程保證了同一時(shí)間只有一個(gè)命令在執(zhí)行,不會(huì)被其他命令打斷。命令隊(duì)列則確保命令按照順序依次執(zhí)行,在執(zhí)行一個(gè)命令的過程中不會(huì)插入其他命令,從而保證了原子性。
訂單系統(tǒng)相關(guān)
- 在訂單每天都是百萬級(jí)別的數(shù)據(jù)量且超過30分鐘未支付系統(tǒng)自動(dòng)取消訂單的場(chǎng)景下,如何設(shè)計(jì)把訂單的狀態(tài)改為取消
- 可以使用Redis的有序集合,以訂單創(chuàng)建時(shí)間加上30分鐘作為score,訂單ID作為member。定時(shí)任務(wù)定期掃描有序集合,取出當(dāng)前時(shí)間超過score的訂單ID,去數(shù)據(jù)庫中更新訂單狀態(tài)為取消。也可以使用消息隊(duì)列延遲消息功能,在訂單創(chuàng)建時(shí)發(fā)送一個(gè)30分鐘后的延遲消息,消息到達(dá)時(shí)更新訂單狀態(tài)。
- 訂單系統(tǒng)中MQ的具體使用場(chǎng)景是什么
- 訂單創(chuàng)建后,發(fā)送消息到MQ通知庫存系統(tǒng)扣減庫存。通知支付系統(tǒng)進(jìn)行支付處理。訂單狀態(tài)變更時(shí),通知相關(guān)系統(tǒng)更新狀態(tài),如通知物流系統(tǒng)訂單已支付待發(fā)貨等。實(shí)現(xiàn)異步解耦,提高系統(tǒng)的穩(wěn)定性和性能。
- 如何保證MQ消息的冪等
- 在消息中添加唯一標(biāo)識(shí),消費(fèi)者在處理消息前先檢查是否已處理過該標(biāo)識(shí)的消息。利用數(shù)據(jù)庫的唯一索引,對(duì)消息中的關(guān)鍵信息建唯一索引,插入時(shí)若沖突則表示重復(fù)消息,不做處理。使用狀態(tài)機(jī),記錄消息處理的狀態(tài),根據(jù)狀態(tài)決定是否處理消息。
RocketMQ相關(guān)
- rocket mq是如何保證消息不丟失的?有沒有做過相關(guān)設(shè)置
- 生產(chǎn)者發(fā)送消息時(shí)采用同步發(fā)送方式,并設(shè)置合理的重試次數(shù)。Broker配置刷盤策略為同步刷盤,保證消息及時(shí)持久化到磁盤。消費(fèi)者采用手動(dòng)提交偏移量,處理完消息后再提交,防止消費(fèi)過程中丟失消息。設(shè)置相關(guān)參數(shù)如unflushDelayMills控制刷盤時(shí)機(jī)等。
微服務(wù)相關(guān)
- 微服務(wù)拆分的原則是什么
- 單一職責(zé)原則,每個(gè)微服務(wù)只負(fù)責(zé)一項(xiàng)主要功能。高內(nèi)聚低耦合,微服務(wù)內(nèi)部功能緊密相關(guān),微服務(wù)之間耦合度低。業(yè)務(wù)邊界清晰,按業(yè)務(wù)模塊進(jìn)行拆分??蓴U(kuò)展性原則,便于獨(dú)立擴(kuò)展和維護(hù)。數(shù)據(jù)獨(dú)立,每個(gè)微服務(wù)有自己獨(dú)立的數(shù)據(jù)庫或數(shù)據(jù)存儲(chǔ)。
- 微服務(wù)中分布式事務(wù)的具體解決的方案是什么?采用的Seata是用的哪種模式,其執(zhí)行過程是什么?這種模式下的隔離級(jí)別和MYSQL的隔離級(jí)別有什么不一樣,會(huì)不會(huì)有什么問題,如何解決
- 解決方案:有兩階段提交、TCC、本地消息表、Seata等。
- Seata模式:以AT模式為例,執(zhí)行過程是開啟全局事務(wù),業(yè)務(wù)操作時(shí)Seata攔截SQL,記錄數(shù)據(jù)的前后鏡像,提交時(shí)協(xié)調(diào)各分支事務(wù)提交,若失敗則根據(jù)鏡像回滾。
- 隔離級(jí)別差異:Seata AT模式默認(rèn)讀未提交,MySQL默認(rèn)可重復(fù)讀。Seata可能存在臟讀問題。
- 問題及解決:可通過在業(yè)務(wù)層控制事務(wù)邊界,結(jié)合MySQL的鎖機(jī)制等,必要時(shí)提高Seata隔離級(jí)別來解決。
數(shù)據(jù)庫相關(guān)
- 公司的SQL語句規(guī)范是什么?表在建立索引的時(shí)候有什么原則
- SQL規(guī)范:命名規(guī)范,表名、字段名等要有意義且遵循統(tǒng)一格式。語句格式化,縮進(jìn)、換行規(guī)范。避免使用SELECT *,明確列出所需字段。合理使用事務(wù)等。
- 索引原則:在經(jīng)常用于查詢條件、連接條件、排序和分組的字段上建立索引。區(qū)分度高的字段優(yōu)先建索引。避免過多索引,考慮索引的維護(hù)成本。聯(lián)合索引遵循最左前綴原則。
23. 為什么不建議用 uuid 作為 MYSQL 的主鍵索引?
- 存儲(chǔ)開銷大:UUID 是 128 位,通常以 36 個(gè)字符的字符串形式存儲(chǔ),相比自增整數(shù)(如 INT 型 4 字節(jié))占用更多存儲(chǔ)空間,增加了索引文件大小。
- 性能影響:
- 插入性能:UUID 無序,插入時(shí)會(huì)導(dǎo)致數(shù)據(jù)頁頻繁分裂,影響插入效率。而自增主鍵按順序插入,數(shù)據(jù)頁分裂頻率低。
- 查詢性能:范圍查詢時(shí),自增主鍵更具優(yōu)勢(shì),因?yàn)槠渲颠B續(xù),利于快速定位數(shù)據(jù)范圍;UUID 無序,無法利用范圍查詢優(yōu)化。
24. select 語句的查詢過程是什么,如何預(yù)防回表?
- 查詢過程:
- 解析與預(yù)處理:MySQL 解析 SQL 語句,檢查語法,生成解析樹,并進(jìn)行預(yù)處理,如權(quán)限檢查、表名和列名解析。
- 優(yōu)化器:分析查詢語句,考慮多種執(zhí)行方案,如索引使用、表連接順序等,基于成本模型選擇最優(yōu)執(zhí)行計(jì)劃。
- 執(zhí)行器:按照?qǐng)?zhí)行計(jì)劃調(diào)用存儲(chǔ)引擎 API,獲取數(shù)據(jù)并返回給客戶端。
- 預(yù)防回表:
- 覆蓋索引:查詢列包含在索引中,避免回表操作。例如,查詢
SELECT col1, col2 FROM table WHERE col3 = 'value'
,若建立(col3, col1, col2)
復(fù)合索引,可利用覆蓋索引直接獲取結(jié)果。 - 減少不必要查詢列:僅查詢索引列可避免回表。
- 覆蓋索引:查詢列包含在索引中,避免回表操作。例如,查詢
25. 在線上給一個(gè)小表加了個(gè)字段結(jié)果導(dǎo)致整個(gè)庫都掛了,原因是什么,如何解決?
- 原因:
- 鎖表問題:在添加字段操作時(shí),MySQL 可能會(huì)使用表鎖,長(zhǎng)時(shí)間占用表資源,導(dǎo)致其他讀寫操作被阻塞,若有大量并發(fā)請(qǐng)求,可能拖垮整個(gè)數(shù)據(jù)庫。
- 磁盤空間不足:添加字段可能導(dǎo)致表結(jié)構(gòu)變更,需要額外磁盤空間。若磁盤空間已滿,操作失敗并可能影響數(shù)據(jù)庫其他功能。
- 解決方法:
- 在線 DDL 工具:使用工具如
pt-online-schema-change
或gh-ost
,它們通過創(chuàng)建臨時(shí)表、復(fù)制數(shù)據(jù)等方式,實(shí)現(xiàn)無鎖或低鎖的表結(jié)構(gòu)變更。 - 提前檢查磁盤空間:在操作前確保有足夠磁盤空間。
- 在線 DDL 工具:使用工具如
26. MYSQL 中是如何出現(xiàn)死鎖的,在設(shè)計(jì)表的時(shí)候如何減少鎖的沖突?
- 死鎖產(chǎn)生原因:兩個(gè)或多個(gè)事務(wù)在獲取資源時(shí),互相等待對(duì)方釋放已占有的資源,形成循環(huán)等待,導(dǎo)致死鎖。例如,事務(wù) A 持有鎖 L1 并請(qǐng)求鎖 L2,事務(wù) B 持有鎖 L2 并請(qǐng)求鎖 L1。
- 減少鎖沖突的表設(shè)計(jì)方法:
- 合理設(shè)計(jì)索引:確保經(jīng)常用于查詢條件的字段有索引,減少全表掃描,降低鎖的粒度和時(shí)間。
- 優(yōu)化事務(wù)順序:按照固定順序訪問資源,避免循環(huán)等待。例如,所有事務(wù)都先訪問表 A 再訪問表 B。
- 降低事務(wù)隔離級(jí)別:在滿足業(yè)務(wù)需求前提下,適當(dāng)降低事務(wù)隔離級(jí)別,減少鎖的持有時(shí)間。
27. 單點(diǎn)登錄系統(tǒng)是用什么協(xié)議來實(shí)現(xiàn)的?如何解決 token 或 session 的跨域問題?
- 常用協(xié)議:
- CAS(Central Authentication Service):簡(jiǎn)單的單點(diǎn)登錄協(xié)議,客戶端通過 CAS 服務(wù)器認(rèn)證,服務(wù)器返回票據(jù),客戶端憑票據(jù)訪問其他應(yīng)用。
- OAuth(開放授權(quán)):用于授權(quán)第三方應(yīng)用訪問用戶資源,用戶在授權(quán)服務(wù)器認(rèn)證后,第三方應(yīng)用獲取授權(quán)令牌訪問資源。
- SAML(Security Assertion Markup Language):基于 XML 的標(biāo)準(zhǔn),用于在不同安全域間交換認(rèn)證和授權(quán)信息。
- 解決跨域問題:
- Token 跨域:通過在響應(yīng)頭設(shè)置
Access - Control - Allow - Origin
允許跨域訪問,前端在請(qǐng)求時(shí)攜帶 Token。也可使用 JSONP 或 CORS 代理方式傳遞 Token。 - Session 跨域:使用 JSONP 傳遞 Session ID,或通過設(shè)置代理服務(wù)器,在代理服務(wù)器上維護(hù)統(tǒng)一的 Session 存儲(chǔ),實(shí)現(xiàn)跨域共享 Session。
- Token 跨域:通過在響應(yīng)頭設(shè)置
28. 如何設(shè)計(jì)和實(shí)現(xiàn)微信掃碼登錄的功能?
- 設(shè)計(jì)思路:
- 前端:展示掃碼登錄按鈕,調(diào)用微信提供的掃碼登錄接口,顯示二維碼。
- 后端:接收微信服務(wù)器回調(diào),驗(yàn)證回調(diào)信息,生成用戶登錄狀態(tài),返回登錄結(jié)果給前端。
- 實(shí)現(xiàn)步驟:
- 注冊(cè)應(yīng)用:在微信開放平臺(tái)注冊(cè)應(yīng)用,獲取 AppID 和 AppSecret。
- 前端生成二維碼:前端調(diào)用微信 JS - SDK 生成帶有唯一標(biāo)識(shí)(如 state 參數(shù))的二維碼,展示給用戶。
- 用戶掃碼:用戶使用微信掃碼,微信服務(wù)器將掃碼信息發(fā)送到后端服務(wù)器。
- 后端驗(yàn)證:后端接收微信回調(diào),使用 AppID 和 AppSecret 驗(yàn)證回調(diào)信息合法性,獲取用戶信息。
- 生成登錄狀態(tài):后端生成用戶登錄狀態(tài)(如 Token),存儲(chǔ)用戶登錄信息,返回登錄結(jié)果給前端。
- 前端處理:前端根據(jù)后端返回結(jié)果,處理登錄成功或失敗邏輯。
在Redis集群中使用Lua鎖
可能會(huì)存在以下一些問題
一致性問題
- 數(shù)據(jù)同步延遲:Redis集群采用異步復(fù)制機(jī)制,主節(jié)點(diǎn)將數(shù)據(jù)復(fù)制到從節(jié)點(diǎn)存在一定延遲。當(dāng)使用Lua腳本獲取鎖時(shí),若主節(jié)點(diǎn)在未完成數(shù)據(jù)同步到從節(jié)點(diǎn)的情況下出現(xiàn)故障,新的主節(jié)點(diǎn)可能沒有鎖的相關(guān)數(shù)據(jù),導(dǎo)致鎖的一致性被破壞,出現(xiàn)多個(gè)客戶端同時(shí)獲取到鎖的情況。
- 網(wǎng)絡(luò)分區(qū)影響:在網(wǎng)絡(luò)分區(qū)場(chǎng)景下,集群可能會(huì)被分割成多個(gè)子集群。若獲取鎖的客戶端所在子集群與持有鎖的主節(jié)點(diǎn)所在子集群隔離,可能會(huì)導(dǎo)致客戶端無法正確判斷鎖的狀態(tài),出現(xiàn)誤判獲取鎖成功的情況,進(jìn)而引發(fā)數(shù)據(jù)不一致等問題。
性能問題
- 腳本執(zhí)行阻塞:Redis是單線程處理命令,Lua腳本在執(zhí)行時(shí)會(huì)阻塞其他命令的執(zhí)行。如果Lua鎖腳本執(zhí)行時(shí)間過長(zhǎng),會(huì)影響Redis對(duì)其他請(qǐng)求的處理能力,降低整個(gè)系統(tǒng)的性能和響應(yīng)速度。
- 集群資源消耗:在集群環(huán)境中,執(zhí)行Lua腳本需要在多個(gè)節(jié)點(diǎn)之間協(xié)調(diào)和同步,這會(huì)增加網(wǎng)絡(luò)開銷和節(jié)點(diǎn)的計(jì)算資源消耗。大量使用Lua鎖可能導(dǎo)致集群資源緊張,影響整體性能。
復(fù)雜性問題
- 腳本編寫難度:編寫正確、高效且能在集群環(huán)境中穩(wěn)定運(yùn)行的Lua鎖腳本具有一定難度。需要開發(fā)者對(duì)Redis集群的工作原理、數(shù)據(jù)一致性模型以及Lua腳本的特性有深入理解,否則容易出現(xiàn)邏輯漏洞和錯(cuò)誤。
- 維護(hù)和調(diào)試?yán)щy:由于Lua鎖腳本在集群中的執(zhí)行涉及多個(gè)節(jié)點(diǎn)和復(fù)雜的網(wǎng)絡(luò)交互,出現(xiàn)問題時(shí)定位和解決問題的難度較大。例如,當(dāng)鎖出現(xiàn)異常釋放或無法獲取的情況時(shí),很難快速確定是腳本邏輯問題、網(wǎng)絡(luò)問題還是節(jié)點(diǎn)故障等原因?qū)е隆?/li>
兼容性問題
- 版本差異:不同版本的Redis對(duì)Lua腳本的支持可能存在差異,某些特性或行為可能在不同版本中有所變化。在使用Lua鎖時(shí),可能會(huì)因?yàn)镽edis版本升級(jí)或集群中節(jié)點(diǎn)版本不一致等原因,導(dǎo)致鎖的行為不符合預(yù)期。
- 與其他模塊沖突:如果Redis集群中還使用了其他模塊或擴(kuò)展,可能會(huì)與Lua鎖產(chǎn)生兼容性問題。例如,某些模塊可能會(huì)修改Redis的命令執(zhí)行邏輯或數(shù)據(jù)結(jié)構(gòu),影響Lua鎖的正常工作。
如何處理Redis中大key
大key的檢測(cè)
- 使用Redis命令:可以使用
MEMORY USAGE
命令來獲取鍵的內(nèi)存占用情況,從而找出大key。例如MEMORY USAGE key
可以返回key
的內(nèi)存占用字節(jié)數(shù)。還可以結(jié)合SCAN
命令,遍歷所有鍵,對(duì)每個(gè)鍵執(zhí)行MEMORY USAGE
來全面檢測(cè)大key。 - 借助Redis工具:利用
redis-cli
的--bigkeys
選項(xiàng),它可以快速掃描并找出內(nèi)存中占用空間較大的鍵。也可以使用Redis的可視化工具,如RedisInsight、RedisDesktopManager等,這些工具通常提供了直觀的界面來展示鍵的大小和分布情況,方便查找大key。
優(yōu)化存儲(chǔ)結(jié)構(gòu)
- 對(duì)象編碼優(yōu)化:Redis的不同數(shù)據(jù)類型有不同的編碼方式,例如
hash
類型如果字段較少且值較小,使用ziplist
編碼會(huì)更節(jié)省空間??梢酝ㄟ^OBJECT ENCODING
命令查看鍵的編碼方式,并考慮是否可以通過調(diào)整數(shù)據(jù)結(jié)構(gòu)或使用合適的命令來優(yōu)化編碼。比如,對(duì)于一個(gè)包含大量小字段的hash
,可以使用HMSET
而不是逐個(gè)HSET
來插入數(shù)據(jù),這樣可能會(huì)使Redis采用更緊湊的編碼。 - 使用壓縮:對(duì)于值是字符串類型的大key,如果內(nèi)容可壓縮,可以在客戶端對(duì)數(shù)據(jù)進(jìn)行壓縮后再存儲(chǔ)到Redis中,獲取數(shù)據(jù)時(shí)再進(jìn)行解壓縮。可以使用
gzip
、zlib
等壓縮庫來實(shí)現(xiàn)。不過要注意壓縮和解壓縮會(huì)帶來一定的CPU開銷,需要根據(jù)實(shí)際情況權(quán)衡。
數(shù)據(jù)拆分
- 按數(shù)據(jù)特征拆分:如果大key是一個(gè)
hash
或list
等集合類型,可以根據(jù)數(shù)據(jù)的業(yè)務(wù)特征將其拆分成多個(gè)小key。例如,一個(gè)包含用戶所有訂單信息的大hash
,可以按照訂單時(shí)間或訂單類型等維度拆分成多個(gè)hash
,每個(gè)hash
只包含部分訂單信息。 - 使用Redis集群:將大key的數(shù)據(jù)分布到多個(gè)Redis節(jié)點(diǎn)上,通過集群的方式來分散存儲(chǔ)和訪問壓力。可以使用Redis的分片集群,如Redis Cluster,它會(huì)根據(jù)鍵的哈希值將數(shù)據(jù)分布到不同的節(jié)點(diǎn)上。在使用Redis Cluster時(shí),需要合理設(shè)計(jì)鍵的命名規(guī)則,確保相關(guān)數(shù)據(jù)能夠均勻分布在各個(gè)節(jié)點(diǎn)上。
過期策略和淘汰機(jī)制
- 設(shè)置合理過期時(shí)間:對(duì)于一些時(shí)效性較強(qiáng)的大key,設(shè)置合適的過期時(shí)間,讓Redis自動(dòng)刪除過期的大key,以釋放內(nèi)存空間。比如緩存類的大key,根據(jù)其業(yè)務(wù)場(chǎng)景設(shè)置幾分鐘到幾小時(shí)不等的過期時(shí)間。
- 調(diào)整淘汰策略:根據(jù)業(yè)務(wù)需求調(diào)整Redis的內(nèi)存淘汰策略。例如,設(shè)置為
volatile-lru
(對(duì)設(shè)置了過期時(shí)間的鍵采用LRU算法淘汰)或allkeys-lru
(對(duì)所有鍵采用LRU算法淘汰),讓Redis在內(nèi)存不足時(shí)優(yōu)先淘汰不常用的大key。也可以結(jié)合maxmemory
配置項(xiàng),合理設(shè)置Redis的最大內(nèi)存使用量,觸發(fā)淘汰機(jī)制。