天天看點

Redis的正确使用姿勢

Redis的正确使用姿勢

前言

說到分布式緩存,可能大多數人腦海浮現的就是redis了,為什麼redis能夠在競争激烈的緩存大戰中脫穎而出呢?原因無非有一下幾點:性能好,豐富的特性跟資料結構,api操作簡單。但是用的人多了,就會出現很多不規範或者疏忽的地方,嚴重的時候甚至會導緻生産事故,是以我們有必要來聊聊在Redis使用過程中的一些“正确姿勢“。

切忌裸奔

大家别笑... 很多初學者或者沒經驗的開發人員在伺服器上用root使用者裝了redis以後,打開預設端口直接就愉快的運作起來了,開放了外網及預設端口的連接配接,甚至對于生産環境也這樣,貪圖一時的友善,這種情況比較多的出現在一些初創公司 (包括N年前的我也這麼幹過...)

那麼會出現什麼問題呢?最常見的就是Redis未授權通路漏洞。攻擊者掃描到網際網路開放的ip以及預設的6379端口後,直接在本地遠端連接配接你伺服器的redis,通過redis的指令将本機生成的公鑰寫入到伺服器的authorized.keys中,這時候本機就可以ssh免密登入進來了。接下來可以寫入反彈shell,提權,然後就可以為所欲為了,這就是為什麼你的伺服器上面會突然出現有挖礦程式的一個原因。

為了防止出現上述的風險,我們可以從以下幾個地方來處理。

  • 修改預設端口6379
  • 綁定内網通路 bing 127.0.0.1
  • 添加redis的密碼驗證
  • 以低權限的使用者運作redis
  • 必要時設定防火牆政策

禁止“ key *” ,用“scan”代替

說到這個,筆者也是滿滿的淚,在年少無知的時候曾經在生産環境執行過這個指令,後來差點收拾背包提前下班了。為什麼這個操作這麼可怕呢?“key *” 操作的意思是傳回資料庫中所有比對的key,它會掃一次性掃描所有的記錄,當你庫裡的資料量很大的時候,會造成redis的阻塞,cpu使用率飙升,慢慢的拖垮項目中對redis的相關請求直至出現各種timeout...

在Redis2.8版本以後,提供了一個更好的周遊key的操作"scan",它類似于我們jdbc中ResultSet,通過一個遊标來疊代。使用方法為“SCAN cursor [MATCH pattern] [COUNT count]”

redis 127.0.0.1:6379> scan 0
1) "17"
2)  1) "key:12"
    2) "key:8"
    3) "key:4"
    4) "key:14"
    5) "key:16"
    6) "key:17"
    7) "key:15"
    8) "key:10"
    9) "key:3"
    10) "key:7"
    11) "key:1"

redis 127.0.0.1:6379> scan 17
1) "0"
2) 1) "key:5"
   2) "key:18"
   3) "key:0"
   4) "key:2"
   5) "key:19"
   6) "key:13"
   7) "key:6"
   8) "key:9"
   9) "key:11"
           

“scan 0 ”表示開始一個新的疊代,當傳回的第一參數為0時,則表示疊代結束,若不為0,下一次疊代的時候帶上這個遊标開始下一次周遊,直到傳回0.第二個參數則是目前周遊出來的值。使用的時候需要注意版本,當版本低于2.8時,需更新才能使用。

key的設計

首先用“:”來分割key是一個約定俗成的東西,自己使用的時候就盡量不要用一些比較特殊的字元來代替。關于我們的key設計可以參照我們的關系型資料庫。

假如有一個user表,有userid,age,username字段,那麼我們key就可以"user:userid:useridValue:username"這麼來設計,把表名作為key的字首,查詢的條件放在最後。中間用字段跟它所對應的value分割開來,所有的設計都是為了在查詢的時候可以更便捷。

合理使用多個db

redis的db下标預設0-15,也就是有16個。通常大部分人都是使用db0,所有的k-v都在一個庫中。這其實沒多大問題,但是redis不是關系型資料庫,存儲的資料互相耦合不那麼大,是以建議可以按照不同的業務把資料分散到各個庫中,這樣我們可以select 不同的 db 來執行不同的業務子產品操作。

善用5種資料結構

redis提供了5種資料結構,但是根據以往的面試結果來看,很多應聘者幾乎在項目中隻用到string類型,甚至對其他類型一知半解。其實當我們能在不同的場景善用不同的結構的話,效率會有很大的提升。下面簡單介紹幾個例子。

SortSet

它提供了一個優先級(score)來排序,我們可以把score的值設定成時間戳,這樣我們可以通過一些定時的操作來取出某段時間裡面資料,在我們項目的機器人子產品中有大量的此類操作。還有常用的地方是排行榜,通過score值的變化來快速高效的更新榜單。

list

它的實作是一個雙向連結清單,我們可以把一些需要執行的任務通過lpush,rpush存放進來,組成符合我們需求的順序,最後我們在依次取出來執行,類似于mq。

set

用來做一些自動去重的操作,比如redis的交集指令,可以取出2個人的共同好友。

禁用高危指令

redis中有很多高危指令。如“flushdb”,“config”等,我們可以禁止或者重命名這些指令來使得操作更加安全。

我們需要修改redis的配置檔案redis.conf,在SECURITY這一項中,新增

       rename-command FLUSHALL ""

       rename-command CONFIG ""

假如是重命名的話

       rename-command FLUSHALL abcdefg

配置完重新開機後生效。

結語

對于redis的話題,其實還有很多,比如釋出訂閱,持久化機制,叢集等。很多最佳實踐都需要結合自身的業務不斷摸索,還是那句話,适合自己的才是最好的。

Redis的正确使用姿勢

喜歡的話,關注一下公衆号《深夜裡的程式猿》,每天更新高品質IT文章~

版權聲明:本文為CSDN部落客「weixin_34195546」的原創文章,遵循CC 4.0 BY-SA版權協定,轉載請附上原文出處連結及本聲明。

原文連結:https://blog.csdn.net/weixin_34195546/article/details/91928817