Redis除了作緩存,還能作什麼

緩存

Redis是什麼你們都知道,一個非關係型數據庫。大部分狀況下咱們使用Redis作緩存。使用緩存的狀況通常是這樣的:面試

圖片Redis緩存數據庫

(1)從Redis緩存中獲取數據,若是存在數據,直接返回值。數組

(2)若是不存在,執行數據庫的查詢方法緩存

(3)將數據庫中的值放入緩存,並返回值網絡

代碼以下:多線程

固然咱們也可使用Spring的緩存註解@Cacheble。咱們要在配置類上面開啓緩存註解@EnableCaching,使用以下:架構

有興趣的童鞋能夠看看我寫的這篇文章:併發

利用AOP自定義Redis緩存註解框架

這篇文章裏我從新開發了緩存註解,增長了兩個功能:設置超時時間設置併發請求數。能夠實現不一樣場景設置不一樣參數。異步

隊列

上面其實就是咱們經常使用的場景,那麼Redis除了作緩存,還能夠作什麼呢?

咱們還可使用Redis作隊列。

圖片Redis隊列

那麼咱們何時可使用Redis的隊列功能呢?

圖片

示例代碼如上。

關於具體使用情形,能夠看看我寫的這篇文章:

個人多線程爬蟲項目實戰

這篇文章的爬蟲項目中,爬取的時候可能由於網絡等緣由,爬取的那一條數據會失敗。這時我會記錄失敗的urlcode,並將爬取異常的urlcode存入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庫存扣減

示例代碼以下:

有興趣的童鞋能夠看看我寫的這篇文章:

一次阿里面試,我被問到了如何設計秒殺系統

Redis分佈式鎖

如今的系統都是集羣部署,每一個服務都不是單節點的了。好比庫存服務,可能部署到3臺機器上分別命名爲節點1,節點2,節點3。庫存服務(使用數據庫如MySQL)須要扣減庫存,扣減庫存確定須要鎖吧,若是使用Lock或者synchronized,只能鎖住本身的節點。而從前臺訪問是隨機路由到這3臺節點的。若是線程一進來使節點1上了鎖,當線程二進來可能訪問到的是節點2,這時節點2尚未上鎖,那麼庫存就會扣減錯誤。而庫存扣減仍是一個核心操做,如今竟然有Bug,想一想就可怕。

Redis分佈式鎖實現思路以下:

  • setnx + 過時時間 用lua腳本保證原子性
  • 鎖持有心跳檢測(防止未解鎖,鎖失效問題)
  • 線程自選獲取鎖

咱們也可使用已有的輪子Redisson框架。

Redis延遲隊列

Redis的zset能夠用於做延遲隊列,score爲延遲的時間點,獲取時順序獲取端口的值,若是當前時間戳等於score則可取出。

示例代碼見上圖。

其餘

Redis還有不少更豐富的功能。好比生成全局的id號(原子自增)、微博點贊次數統計(原子自增)、布隆過濾器(Bitmap)、排行榜實現(zset)、地理位置查詢(GEO)、生產者消費者(Stream)、發佈訂閱。

有興趣的能夠看看個人這篇文章:

Redis進階

這篇文章就寫到這裏啦,歡迎你們留言本身在項目中如何使用Redis的。

相關文章
相關標籤/搜索