Web 功能測試下的 Redis快取資料庫
做web功能測試,最應該瞭解的一塊知識點 。
作為一名出色的功能測試工程師,真的不是隨便點點就可以,需要從多方面去了解一個專案,一個系統的原理,配置,才可以更好,更完善的做好測試。
今天給大家分享一篇關於Redis的作用和使用場景的文章。
1、Redis
一、為什麼使用
解決應用伺服器的cpu和記憶體壓力
減少io的讀操作,減輕io的壓力
關係型資料庫的擴充套件性不強,難以改變表結構
二、優點:
nosql資料庫沒有關聯關係,資料結構簡單,拓展表比較容易
nosql讀取速度快,對較大資料處理快
三、適用場景:
資料高併發的讀寫
海量資料的讀寫
對擴充套件性要求高的資料
四、不適場景:
需要事務支援(非關係型資料庫)
基於sql結構化查詢儲存,關係複雜
五、Redis結構:
Redis是一個開源的key—value型資料庫,支援string、list、set、zset和hash型別資料。對這些資料的操作都是原子性的,redus為了保證效率會定期持久化資料。
六、使用場景:
配合關係型資料庫做快取記憶體
快取高頻次訪問的資料,降低資料庫io
分散式架構,做session共享
可以持久化特定資料。
利用zset型別可以儲存排行榜
利用list的自然時間排序儲存最新n個數據
七、Linux下redis:
redis目錄:usr/local/bin
linux下redis常用命令:
redis-benchmark:效能測試工具
redis-server:啟動redis伺服器
redis-cli:啟動redis客戶端,操作入口
八、Redis基礎知識
埠:6379
預設16個數據庫,下標從0開始
單執行緒:redis是單執行緒+io多路複用:檢查檔案描述的就緒狀態
Memchached:多執行緒+鎖
redis資料型別:String set list hash zset
2、redis 實際應用中的快取作用
有人說網際網路使用者是用腳投票的,這句話其實也從側面說明了,使用者體驗是多麼的重要;這就要求在軟體架構設計時,不但要注重可靠性、安全性、可擴充套件性以及可維護性等等的一些指標,更要注重使用者的體驗,使用者體驗分很多方面,但是有一點非常重要就是對使用者操作的響應一定要快;怎樣提高使用者訪問的響應速度,這就是擺在架構設計中必須要解決的問題;說道提高服務的響應速度就不得不說快取了;
從系統的層面說,CPU的速度遠遠高於磁碟IO的速度;所以要想提高響應速度,必須減少磁碟IO的操作,但是有很多資訊又是存在資料庫當中的,每次查詢資料庫就是一次IO操作;比如查詢使用者資訊的例子。
通常如下圖:
請求響應時間等於網路響應時間和伺服器響應時間;網路我們控制不了,伺服器響應時間包括CPU計算時間和磁碟IO時間。
其中CPU計算時間這個有硬體資源決定的,我們儘量減少演算法的複雜度來減少它,磁碟IO時間,這個時間是非常慢的,應該儘量減少;
當客戶端呼叫getUser介面的查詢使用者資訊的時候,執行順序1、2、3、4;由於使用者資訊存放在DB中,所以2、3就有一次磁碟IO;這個看似非常簡單業務邏輯,但是當你做架構設計的時候往往要考慮最壞的場景,或者當成千上萬的使用者頻繁的呼叫這個介面應該怎麼處理?
如果按照上圖這樣的架構處理,這個看似簡單業務的介面會使整個系統變慢,這樣使用者的請求就會長時間得不到響應;這樣的問題怎麼解決那,這時候就該快取登場了;
談到快取有幾種形式,其中最簡單的是在每個程序中開闢一塊記憶體,存放快取的資訊,每次先從記憶體查… … 但是在一個分散式或者叢集的環境中,getUser的介面可能會部署多套,每個程序的的記憶體是不能共享、相互獨立的,這就悲劇了;
還有一種使用一個第三方的快取也叫公共快取(比如redis、memcache等);不論部署多少個包含getUser介面的服務,都去訪問同一套快取,那結果就不一樣了。
看一下下面這幅圖:
有Redis,當用客戶端呼叫getUser介面查詢使用者資訊的時候,getUser介面直接去redis中查詢,如果redis中有該使用者資訊,直接返回,避免查詢DB,從而避免了磁碟IO操作;
如果redis中沒有該使用者資訊,則從DB查詢,並且把該使用者資訊存放到redis中;這樣在服務介面(getUser)和DB中間,增加了一個快取層;看似邏輯增加了,其實當面對高併發的時候,比如上邊提到的頻繁查詢使用者資訊的情況,只有第一次查詢有磁碟IO操作,以後只要redis中存在就沒必要再查詢資料庫了;由於沒有了磁碟IO操作,並且redis所有資料都在記憶體操作,所以速度回大大提升;
我們上面用到的快取是redis,其實常用的還有memcache等,它們都提供了叢集模式,並且都是直接記憶體操作,所以速度特別快,也是目前業內使用的比較熱門的技術;
redis相對於memcache提供了更豐富的資料型別,根據不同的業務場景可以選在不同的資料型別;redis本身也提供了主從模式、叢集模式;也有第三方的比如codis提供了redis叢集解決方案;這次咱們主要聊快取在架構設計中的作用,等有機會詳細介紹redis的使用;
總之一句話,要想提高系統的效能,儘量減少IO的操作,特別是磁碟IO的操作;使用快取可以有效的避免這種情況;所以在架構設計過程中,社交到查詢資料庫的時候,應該考慮一下是不是考慮使用快取技術來提高系統的效能,並且降低資料庫的負載。
3、Redis的7個應用場景
一、快取——熱資料
熱點資料(經常會被查詢,但是不經常被修改或者刪除的資料),首選是使用redis快取,畢竟強大到冒泡的QPS和極強的穩定性不是所有類似工具都有的,而且相比於memcached還提供了豐富的資料型別可以使用,另外,記憶體中的資料也提供了AOF和RDB等持久化機制可以選擇,要冷、熱的還是忽冷忽熱的都可選。
結合具體應用需要注意一下:很多人用spring的AOP來構建redis快取的自動生產和清除,過程可能如下:
Select 資料庫前查詢redis,有的話使用redis資料,放棄select 資料庫,沒有的話,select 資料庫,然後將資料插入redis
update或者delete資料庫錢,查詢redis是否存在該資料,存在的話先刪除redis中資料,然後再update或者delete資料庫中的資料。
上面這種操作,如果併發量很小的情況下基本沒問題,但是高併發的情況請注意下面場景:
為了update先刪掉了redis中的該資料,這時候另一個執行緒執行查詢,發現redis中沒有,瞬間執行了查詢SQL,並且插入到redis中一條資料,回到剛才那個update語句,這個悲催的執行緒壓根不知道剛才那個該死的select執行緒犯了一個彌天大錯!於是這個redis中的錯誤資料就永遠的存在了下去,直到下一個update或者delete。
二、計數器
諸如統計點選數等應用。由於單執行緒,可以避免併發問題,保證不會出錯,而且100%毫秒級效能!爽。
命令:INCRBY
當然爽完了,別忘記持久化,畢竟是redis只是存了記憶體!
三、佇列
相當於訊息系統,ActiveMQ,RocketMQ等工具類似,但是個人覺得簡單用一下還行,如果對於資料一致性要求高的話還是用RocketMQ等專業系統。
由於redis把資料新增到佇列是返回新增元素在佇列的第幾位,所以可以做判斷使用者是第幾個訪問這種業務
佇列不僅可以把併發請求變成序列,並且還可以做佇列或者棧使用
四、位操作(大資料處理)
用於資料量上億的場景下,例如幾億使用者系統的簽到,去重登入次數統計,某使用者是否線上狀態等等。
想想一下騰訊10億使用者,要幾個毫秒內查詢到某個使用者是否線上,你能怎麼做?千萬別說給每個使用者建立一個key,然後挨個記(你可以算一下需要的記憶體會很恐怖,而且這種類似的需求很多,騰訊光這個得多花多少錢。。)好吧。這裡要用到位操作——使用setbit、getbit、bitcount命令。
原理是:redis內構建一個足夠長的陣列,每個陣列元素只能是0和1兩個值,然後這個陣列的下標index用來表示我們上面例子裡面的使用者id(必須是數字哈),那麼很顯然,這個幾億長的大陣列就能通過下標和元素值(0和1)來構建一個記憶系統,上面我說的幾個場景也就能夠實現。用到的命令是:setbit、getbit、bitcount
五、分散式鎖與單執行緒機制
驗證前端的重複請求(可以自由擴充套件類似情況),可以通過redis進行過濾:每次請求將request Ip、引數、介面等hash作為key儲存redis(冪等性請求),設定多長時間有效期,然後下次請求過來的時候先在redis中檢索有沒有這個key,進而驗證是不是一定時間內過來的重複提交
秒殺系統,基於redis是單執行緒特徵,防止出現數據庫“爆破”
全域性增量ID生成,類似“秒殺”
六、最新列表
例如新聞列表頁面最新的新聞列表,如果總數量很大的情況下,儘量不要使用select a from A limit 10這種low貨,嘗試redis的 LPUSH命令構建List,一個個順序都塞進去就可以啦。不過萬一記憶體清掉了咋辦?也簡單,查詢不到儲存key的話,用mysql查詢並且初始化一個List到redis中就好了。
七、排行榜
誰得分高誰排名往上。命令:ZADD(有續集,sorted set)
最近在研究股票,發現量化交易是個非常好的辦法,通過臆想出來規律,用程式對歷史資料進行驗證,來判斷這個臆想出來的規律是否有效,這玩意真牛!