redis能夠知足不少的應用場景,並且由於將全部數據都放到內存中,因此它的讀寫性能很好,不少公司都在使用redis。redis給咱們帶來便利的同時,使用過程當中會存在什麼問題呢,本文將簡單加以總結。linux
阻塞問題
redis使用了單線程來處理請求,爲何單線程能夠支持如此高的併發呢?主要有以下幾點:redis
單線程:避免了線程切換和競態產生的消耗,簡化了數據結構和算法的實現
所以若是某個命令執行時間過長,會形成其餘命令阻塞,對redis來講是致命的算法
產生阻塞的場景: A. API或數據結構使用不合理 a. 避免使用某些易形成阻塞的命令如:keys sort hgetall smembers 執行showlog get [n] 能夠獲取最近n條執行慢的記錄,對於執行超過必定時間 (默認10ms,線上建議設置爲1ms)的命令都會記錄到一個定長隊列(默認128,可調整)中。 b. 防止一次操做獲取過多數據:縮減大對象或者把大對象拆分爲多個小對象 發現大對象的命令:redis-cli -h{ip} -p{port} bigkeys 內部原理:採用分段進行scan操做,把歷史掃描過的大對象統計出來 c. 防止大量key同時過時:若是有不少key在同一秒內過時,超過了全部key的25%,redis主線程就會阻塞直到過時key比例降低到25%之內, 所以要避免同一時間過時大量key,過時時間可作散列處理。 redis4.0引入的lazyfree機制能夠避免del、flushdb、flushall、rename等命令引發的redis-server阻塞,提升服務穩定性。 B. CPU飽和 單線程的redis處理命令時只能使用一個CPU,CPU飽和是指redis把單核的CPU使用率跑到接近100%。 首先要肯定redis的併發量是否達到極限,經過redis-cli-h{ip} -p{port}--stat 獲取redis當前使用狀況。 若是達到每秒6w+左右的qps,說明單臺已跑到極限,須要水平擴展。 若是qps只有幾百或者幾千CPU就已經飽和,可能使用了高算法複雜度的命令或者是對內存的過分優化 (如放寬了ziplist的使用條件,雖然使用的內存會變少,可是更耗CPU)。 C. 持久化操做 持久化引發主線程的阻塞操做主要有:fork阻塞、AOF刷盤阻塞、HugePage寫操做阻塞 a. fork阻塞 發生在RDB和AOF重寫時,redis主線程調用fork操做產生共享內存的子線程,由子線程完成持久化文件的重寫工做,若fork操做耗時過長會引發阻塞。 避免使用內存過大的實例。 b. AOF刷盤阻塞 開啓AOF持久化功能時,通常會採用1次/s的刷盤方式,後臺線程每秒對AOF文件作fsync操做,當硬盤壓力過大時fsync操做須要等待直到寫入完成。 若是主線程距離上一次的fsync成功超過2s,爲了數據安全會阻塞直到後臺線程執行完fsync完成。這種阻塞是因爲磁盤壓力引發。 儘可能獨立部署 c. HugePage寫操做阻塞 子進程在執行重寫期間利用linux的copyonwrite機制,會拖慢寫操做的執行時間,致使大量寫操做慢查詢。 優化linux配置
緩存穿透
緩存穿透是指查詢一個根本不存在的數據,緩存層和存儲層都不命中,且不將空結果寫到緩存中。
會致使後端存儲負載變大,形成後端存儲宕機等問題。能夠在程序中分別統計總調用數、緩存命中數、存儲命中數,如有大量存儲層空命中,多是出現了緩存穿透。
產生緣由:1.自身代碼或數據出現問題 2.惡意攻擊,爬蟲形成空命中
如何解決:後端