Redis是什麼你們都知道,一個非關係型數據庫。大部分狀況下咱們使用Redis作緩存。使用緩存的狀況通常是這樣的:面試
Redis緩存數據庫
「(1)從Redis緩存中獲取數據,若是存在數據,直接返回值。數組
(2)若是不存在,執行數據庫的查詢方法緩存
(3)將數據庫中的值放入緩存,並返回值網絡
」
代碼以下:多線程
固然咱們也可使用Spring的緩存註解@Cacheble
。咱們要在配置類上面開啓緩存註解@EnableCaching
,使用以下:架構
有興趣的童鞋能夠看看我寫的這篇文章:併發
「 」
這篇文章裏我從新開發了緩存註解,增長了兩個功能:設置超時時間和設置併發請求數。能夠實現不一樣場景設置不一樣參數。異步
上面其實就是咱們經常使用的場景,那麼Redis除了作緩存,還能夠作什麼呢?
咱們還可使用Redis作隊列。
Redis隊列
那麼咱們何時可使用Redis的隊列功能呢?
示例代碼如上。
關於具體使用情形,能夠看看我寫的這篇文章:
「 」
這篇文章的爬蟲項目中,爬取的時候可能由於網絡等緣由,爬取的那一條數據會失敗。這時我會記錄失敗的url
或code
,並將爬取異常的url
或code
存入Redis隊列。
我在後臺從新啓動一個線程,自旋的形式將Redis的隊列中的數據阻塞式取出。而後再一次爬取。
Redis爬蟲
咱們可使用Redis的Bitmap存儲簽到數據。
Bitmap是一個二進制的數組,長度不限(當長度爲20億時,佔用內存200多MB)。數組內的值爲0或1。
使用Redis的Bitmap,速度很快,在高併發狀況下有更優良的性能。並且佔用空間很小,Bitmap大約能夠存儲個bit位(bit數組大約五六億的長度)。
例如:sign:1:202009
表示id爲1的用戶2020年9月的簽到記錄。
Java示例代碼以下:
jedis.bitfield(buildSignKey(userId, date), "GET", type, "0");
具體使用狀況能夠看看我寫的這篇文章:
「 」
在秒殺系統中,使用Redis來存儲庫存數量,當用戶發起搶購請求時,先判斷Redis中的庫存是否可用。若是可用,將搶購請求放入分佈式隊列中,採用異步方式處理後續操做,並完成下單。同時在Redis中做庫存扣減。
Redis庫存扣減
示例代碼以下:
有興趣的童鞋能夠看看我寫的這篇文章:
「 」
如今的系統都是集羣部署,每一個服務都不是單節點的了。好比庫存服務,可能部署到3臺機器上分別命名爲節點1,節點2,節點3。庫存服務(使用數據庫如MySQL)須要扣減庫存,扣減庫存確定須要鎖吧,若是使用Lock
或者synchronized
,只能鎖住本身的節點。而從前臺訪問是隨機路由到這3臺節點的。若是線程一進來使節點1上了鎖,當線程二進來可能訪問到的是節點2,這時節點2尚未上鎖,那麼庫存就會扣減錯誤。而庫存扣減仍是一個核心操做,如今竟然有Bug,想一想就可怕。
Redis分佈式鎖實現思路以下:
「」
setnx
+ 過時時間 用lua
腳本保證原子性- 鎖持有心跳檢測(防止未解鎖,鎖失效問題)
- 線程自選獲取鎖
咱們也可使用已有的輪子Redisson
框架。
Redis的zset
能夠用於做延遲隊列,score
爲延遲的時間點,獲取時順序獲取端口的值,若是當前時間戳等於score
則可取出。
示例代碼見上圖。
Redis還有不少更豐富的功能。好比生成全局的id號(原子自增)、微博點贊次數統計(原子自增)、布隆過濾器(Bitmap)、排行榜實現(zset)、地理位置查詢(GEO)、生產者消費者(Stream)、發佈訂閱。
有興趣的能夠看看個人這篇文章:
「 」
這篇文章就寫到這裏啦,歡迎你們留言本身在項目中如何使用Redis的。