摘要:給我們帶來便利的同時,使用過程中會存在什么問題呢,本文將簡單加以總結(jié)。避免使用內(nèi)存過大的實例。如果主線程距離上一次的成功超過,為了數(shù)據(jù)安全會阻塞直到后臺線程執(zhí)行完完成。
redis可以滿足很多的應(yīng)用場景,而且因為將所有數(shù)據(jù)都放到內(nèi)存中,所以它的讀寫性能很好,很多公司都在使用redis。redis給我們帶來便利的同時,使用過程中會存在什么問題呢,本文將簡單加以總結(jié)。
阻塞問題
redis使用了單線程來處理請求,為什么單線程可以支持如此高的并發(fā)呢?主要有如下幾點:
純內(nèi)存訪問:將所有數(shù)據(jù)都放到內(nèi)存中,內(nèi)存響應(yīng)時間為100納秒,是redis達到每秒萬級別訪問的重要基礎(chǔ)
非阻塞IO:redis使用epoll作為I/O多路復(fù)用技術(shù),redis自身的事件處理模型將epoll中的連接、讀寫、關(guān)閉都轉(zhuǎn)換為事件,不在網(wǎng)絡(luò)I/O上浪費過多時間
單線程:避免了線程切換和競態(tài)產(chǎn)生的消耗,簡化了數(shù)據(jù)結(jié)構(gòu)和算法的實現(xiàn)
因此如果某個命令執(zhí)行時間過長,會造成其他命令阻塞,對redis來說是致命的
產(chǎn)生阻塞的場景: A. API或數(shù)據(jù)結(jié)構(gòu)使用不合理 a. 避免使用某些易造成阻塞的命令如:keys sort hgetall smembers 執(zhí)行showlog get [n] 可以獲取最近n條執(zhí)行慢的記錄,對于執(zhí)行超過一定時間 (默認10ms,線上建議設(shè)置為1ms)的命令都會記錄到一個定長隊列(默認128,可調(diào)整)中。 b. 防止一次操作獲取過多數(shù)據(jù):縮減大對象或者把大對象拆分為多個小對象 發(fā)現(xiàn)大對象的命令:redis-cli -h{ip} -p{port} bigkeys 內(nèi)部原理:采用分段進行scan操作,把歷史掃描過的大對象統(tǒng)計出來 c. 防止大量key同時過期:如果有很多key在同一秒內(nèi)過期,超過了所有key的25%,redis主線程就會阻塞直到過期key比例下降到25%以內(nèi), 因此要避免同一時間過期大量key,過期時間可做散列處理。 redis4.0引入的lazyfree機制可以避免del、flushdb、flushall、rename等命令引起的redis-server阻塞,提高服務(wù)穩(wěn)定性。 B. CPU飽和 單線程的redis處理命令時只能使用一個CPU,CPU飽和是指redis把單核的CPU使用率跑到接近100%。 首先要確定redis的并發(fā)量是否達到極限,通過redis-cli-h{ip} -p{port}--stat 獲取redis當(dāng)前使用情況。 如果達到每秒6w+左右的qps,說明單臺已跑到極限,需要水平擴展。 如果qps只有幾百或者幾千CPU就已經(jīng)飽和,可能使用了高算法復(fù)雜度的命令或者是對內(nèi)存的過度優(yōu)化 (如放寬了ziplist的使用條件,雖然使用的內(nèi)存會變少,但是更耗CPU)。 C. 持久化操作 持久化引起主線程的阻塞操作主要有:fork阻塞、AOF刷盤阻塞、HugePage寫操作阻塞 a. fork阻塞 發(fā)生在RDB和AOF重寫時,redis主線程調(diào)用fork操作產(chǎn)生共享內(nèi)存的子線程,由子線程完成持久化文件的重寫工作,若fork操作耗時過長會引起阻塞。 避免使用內(nèi)存過大的實例。 b. AOF刷盤阻塞 開啟AOF持久化功能時,一般會采用1次/s的刷盤方式,后臺線程每秒對AOF文件做fsync操作,當(dāng)硬盤壓力過大時fsync操作需要等待直到寫入完成。 如果主線程距離上一次的fsync成功超過2s,為了數(shù)據(jù)安全會阻塞直到后臺線程執(zhí)行完fsync完成。這種阻塞是由于磁盤壓力引起。 盡量獨立部署 c. HugePage寫操作阻塞 子進程在執(zhí)行重寫期間利用linux的copyonwrite機制,會拖慢寫操作的執(zhí)行時間,導(dǎo)致大量寫操作慢查詢。 優(yōu)化linux配置
緩存穿透
緩存穿透是指查詢一個根本不存在的數(shù)據(jù),緩存層和存儲層都不命中,且不將空結(jié)果寫到緩存中。
會導(dǎo)致后端存儲負載變大,造成后端存儲宕機等問題。可以在程序中分別統(tǒng)計總調(diào)用數(shù)、緩存命中數(shù)、存儲命中數(shù),若有大量存儲層空命中,可能是出現(xiàn)了緩存穿透。
產(chǎn)生原因:1.自身代碼或數(shù)據(jù)出現(xiàn)問題 2.惡意攻擊,爬蟲造成空命中
如何解決:
緩存空對象
存儲層不命中,扔將空對象保存到緩存層。
適用場景:數(shù)據(jù)頻繁變化、實時性高
帶來問題:
a.緩存了空值,會占用內(nèi)存空間;可以設(shè)置較短過期時間,自動剔除。
b.數(shù)據(jù)不一致,若存儲層添加了此數(shù)據(jù),有短暫不一致;可主動清除掉緩存的空對象。
布隆過濾器
在訪問緩存層和數(shù)據(jù)層之前將存在的key用布隆過濾器提前保存起來,做第一層攔截。
適用場景:大用戶集,實時性要求較低的場景,如有幾億的數(shù)據(jù)集,每隔一段時間會新增用戶進去,在更新之前新用戶的訪問會存在緩存穿透問題。
缺點:代碼維護復(fù)雜
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/61950.html
摘要:使用中存在的問題及如何避免一闡述了的阻塞問題及緩存穿透問題,本文將繼續(xù)總結(jié)在使用中的問題及方案。更多的節(jié)點不代表更高的性能,這就是無底洞問題。可使用漏桶令牌桶等方式進行限流操作,將流量擋在應(yīng)用上層。 redis使用中存在的問題及如何避免(一)闡述了redis的阻塞問題及緩存穿透問題,本文將繼續(xù)總結(jié)redis在使用中的問題及方案。 無底洞問題 隨著數(shù)據(jù)量和訪問量的增長,需要增加更多...
閱讀 2450·2021-10-11 10:57
閱讀 1300·2021-10-09 09:59
閱讀 2014·2019-08-30 15:53
閱讀 3228·2019-08-30 15:53
閱讀 1028·2019-08-30 15:45
閱讀 759·2019-08-30 15:44
閱讀 3470·2019-08-30 14:24
閱讀 968·2019-08-30 14:21