Redis是由意大利人Salvatore Sanfilippo(網名:antirez)開發的一款內存高速緩存數據庫。Redis全稱爲:Remote Dictionary Server(遠程數據服務),該軟件使用C語言編寫,Redis是一個key-value存儲系統,它支持豐富的數據類型,如:string、list、set、zset(sorted set)、hash。html
Redis支持多種數據類型,有String、List、Hash、Set、zset面試
String類型是二進制安全的,意思是Redis的String能夠包含任何數據,好比圖片或者序列化的對象等。一個Redis中字符串的value最多能夠是512M。通常作一些複雜的計數功能的緩存。redis
List是按照插入順序排序的字符串鏈表。數據庫
從元素插入和刪除的效率視角來看,若是咱們是在鏈表的兩頭插入或刪除元素,這將會是很是高效的操做,即便鏈表中已經存儲了百萬條記錄,該操做也能夠在常量時間內完成。然而須要說明的是,若是元素插入或刪除操做是做用於鏈表中間,那將會是很是低效的 。後端
Redis鏈表常常會被用於消息隊列的服務,以完成多程序之間的消息交換。假設一個應用程序正在執行LPUSH操做向鏈表中添加新的元素,咱們一般將這樣的程序稱之爲"生產者(Producer)",而另一個應用程序正在執行RPOP操做從鏈表中取出元素,咱們稱這樣的程序爲"消費者(Consumer)"。若是此時,消費者程序在取出消息元素後馬上崩潰,因爲該消息已經被取出且沒有被正常處理,那麼咱們就能夠認爲該消息已經丟失,由此可能會致使業務數據丟失,或業務狀態的不一致等現象的發生。然而經過使用RPOPLPUSH命令,消費者程序在從主消息隊列中取出消息以後再將其插入到備份隊列中,直到消費者程序完成正常的處理邏輯後再將該消息從備份隊列中刪除。同時咱們還能夠提供一個守護進程,當發現備份隊列中的消息過時時,能夠從新將其再放回到主消息隊列中,以便其它的消費者程序繼續處理。緩存
能夠利用 lrange 命令,作基於 Redis 的分頁功能,性能極佳,用戶體驗好安全
Hash是一個健值對集合,是一個String類型的key與value的映射表,特別適合用於存儲對象。 可用於存儲、讀取、修改用戶屬性, Hash 結構可使你像在數據庫中 Update 一個屬性同樣只修改某一項屬性值。服務器
Set 是一個集合,集合的概念就是一堆不重複值的組合。利用 Redis 提供的 Set 數據結構,能夠存儲一些集合性的數據。 集合是經過哈希表實現的,因此添加,刪除,查找的複雜度都是O(1) 。Redis 很是人性化的爲集合提供了求交集、並集、差集等操做,那麼就能夠很是方便的實現如共同關注、共同喜愛、二度好友等功能 。也能夠作全局去重的功能。數據結構
和Sets相比,Sorted Sets是將 Set 中的元素增長了一個權重參數 score,使得集合中的元素可以按 score 進行有序排列。能夠作排行榜應用,取 TOP N 操做。Sorted Set 能夠用來作延時任務。最後一個應用就是能夠作範圍查找。多線程
性能和併發。
性能:將一些耗時比較久,且結果不常常變更的SQL,放到Redis中,這樣,請求直接從緩存中讀取,使得可以迅速響應。
併發:大併發的狀況下,全部的請求直接訪問數據庫,數據庫會出現鏈接異常。這個時候,就須要使用Redis作一個緩衝操做,讓請求先訪問到redis,而不是直接訪問數據庫 。
什麼是非阻塞I/O呢?
阻塞與非阻塞能夠簡單理解爲調用一個IO操做能不能當即獲得返回應答,若是不能當即得到返回,須要等待,那就阻塞了;不然就能夠理解爲非阻塞。
什麼是I/O多路複用機制呢?
單個線程,經過記錄跟蹤每一個I/O流(sock)的狀態,來同時管理多個I/O流 。
I/O多路複用的優點並非對於單個鏈接能處理的更快,而是在於能夠在單個線程/進程中處理更多的鏈接。與多進程和多線程技術相比,I/O多路複用技術的最大優點是系統開銷小,系統沒必要建立進程/線程,也沒必要維護這些進程/線程,從而大大減少了系統的開銷。
Redis採用的過時策略是:按期刪除+惰性刪除策略。
按期刪除,Redis 默認每隔100ms 檢查,是否有過時的 Key,有過時 Key 則刪除。
須要說明的是,Redis 不是每隔100ms 將全部的 Key 檢查一次,而是隨機抽取進行檢查(若是每隔 100ms,所有 Key 進行檢查,Redis 豈不是卡死)。
按期刪除能夠經過: 第1、配置redis.conf 的hz選項,默認爲10 (即1秒執行10次,100ms一次,值越大說明刷新頻率越快,最Redis性能損耗也越大,建議不要超過100) 第2、配置redis.conf的maxmemory最大值,當已用內存超過maxmemory限定時,就會觸發主動清理策略
所以,若是隻採用按期刪除策略,會致使不少 Key 到時間沒有刪除。因而,惰性刪除派上用場。
也就是說在你獲取某個 Key 的時候,Redis 會檢查一下,這個 Key 若是設置了過時時間,若是過時了,此時就會刪除。
過時策略能夠參考:[Redis數據過時策略詳解](https://www.cnblogs.com/xuliangxing/p/7151812.html)
可是當某些key沒有被按期刪除到,也沒有獲取某些key,內存豈不是也會佔用很高,這時候就須要內存淘汰機制了
在 redis.conf 中有一行配置
# maxmemory-policy volatile-lru
Redis內存淘汰策略有(觸發該策略的機制是 當內存不足以容納新寫入數據時):
首先,採起正確更新策略,先更新數據庫,再刪緩存。其次,由於可能存在刪除緩存失敗的問題,提供一個補償措施便可,例如利用消息隊列。
緩存穿透:黑客故意去請求緩存中不存在的數據,致使全部的請求都懟到數據庫上,從而數據庫鏈接異常。
解決方法:
緩存雪崩:當緩存服務器重啓或者大量緩存集中在某一個時間段失效,來了一批請求,請求所有到DB,DB瞬時壓力太重雪崩。
解決方法:
緩存擊穿:對於一些設置了過時時間的key,若是這些key可能會在某些時間點被超高併發地訪問,是一種很是「熱點」的數據。這個時候,須要考慮一個問題:緩存被「擊穿」的問題,這個和緩存雪崩的區別在於這裏針對某一key緩存,前者則是不少key。 緩存在某個時間點過時的時候,剛好在這個時間點對這個Key有大量的併發請求過來,這些請求發現緩存過時通常都會從後端DB加載數據並回設到緩存,這個時候大併發的請求可能會瞬間把後端DB壓垮。
解決方法:
參考:
使用keys指令能夠掃出指定模式的key列表。若是這個redis正在給線上的業務提供服務,keys指令會致使線程阻塞一段時間,線上服務會停頓,直到指令執行完畢,服務才能恢復。這個時候可使用scan指令,scan指令能夠無阻塞的提取出指定模式的key列表,可是會有必定的重複機率,在客戶端作一次去重就能夠了,可是總體所花費的時間會比直接用keys指令長。
通常使用list結構做爲隊列,rpush生產消息,lpop消費消息。當lpop沒有消息的時候,要適當sleep一會再重試。 若是不用sleep,list還有個指令叫blpop,在沒有消息的時候,它會阻塞住直到消息到來。
使用pub/sub主題訂閱者模式,能夠實現1:N的消息隊列。 也就是生產一次消費屢次。可是使用pub/sub是有缺點的,在消費者下線的狀況下,生產的消息會丟失,得使用專業的消息隊列如rabbitmq等。
redis如何實現延時隊列:使用sortedset,拿時間戳做爲score,消息內容做爲key,調用zadd來生產消息,消費者用zrangebyscore指令獲取N秒以前的數據輪詢進行處理。
主要是使用了redis 的setnx命令,緩存了鎖,reids緩存的key是鎖的key,全部的共享, value是鎖的到期時間(注意:這裏把過時時間放在value了,沒有時間上設置其超時時間)。
1.經過setnx嘗試設置某個key的值,成功(當前沒有這個鎖)則返回,成功得到鎖
2.鎖已經存在則獲取鎖的到期時間,和當前時間比較,超時的話,則設置新的值
實現方法能夠參考:Redis分佈式鎖實現