redis的database差點造成的事故

前言

之前在項目中做一個發放第三方兌換券的功能。第三方券保存在數據庫中,一張券是一條記錄,用戶在購買我們商品的時候,我們在數據庫中抽取一張未發放的兌換券發放給用戶。這個功能很簡單,需要考慮分佈式服務的併發場景,當時使用redis加分佈式鎖避免在併發場景下兌換券被重複發放問題,當時有兩個業務服務都集成了這個功能並且由不同的開發人員完成,用的都是同一張表中兌換券,也都是用的redis鎖做併發控制。測試在對這兩個服務同時進行併發測試的時候發現了券被併發領取的問題,這分明就是redis鎖沒有鎖住導致的。後來發現是測試環境兩個服務redis配置的database不一樣導致的。那redis中的database到底是啥,這裏和大家一起學習下。

redis中的database由來

redis是一個字典結構的存儲服務器,一個redis實例提供了多個用來存儲數據的字典,客戶端可以指定將數據存儲在哪個字典中。這與在一個關係數據庫實例中可以創建多個數據庫類似,所以可以將其中的每個字典都理解成一個獨立的數據庫。獨立數據庫中存儲的數據自然也是不相互關聯的。redis默認支持16個數據庫,可以通過調整redis的配置文件redis/redis.conf中的databases來修改這一個值,設置完畢後重啓redis便完成配置。客戶端與redis建立連接後會默認選擇0號數據庫,不過可以隨時使用SELECT命令更換數據庫。建立連接之後SELECT 1就切換到db1上了。springboot項目中可以指定具體的database

spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=123456
spring.redis.database=1
spring.redis.pool.max-idle=1000
spring.redis.pool.min-idle=0
spring.redis.pool.max-active=1000
spring.redis.pool.max-wait=-1

擼擼database的概念

由於redis不支持自定義數據庫的名字,所以每個數據庫都以編號命名。開發者則需要自己記錄存儲的數據與數據庫的對應關係。另外redis也不支持爲每個數據庫設置不同的訪問密碼,所以一個客戶端要麼可以訪問全部數據庫,要麼全部數據庫都沒有權限訪問。但是,要正確地理解redis的database概念這裏不得不提到一個命令,清空一個redis實例中所有數據庫中的數據

redis 127.0.0.1:6379> FLUSHALL

該命令可以清空實例下的所有數據庫數據,這與我們所熟知的關係型數據庫所不同。關係型數據庫多個庫常用於存儲不同應用程序的數據 ,且沒有方式可以同時清空實例下的所有庫數據。所以對於Redis來說這些db更像是一種命名空間,不適宜使用0號數據庫存儲A應用的數據而使用1號數據庫B應用的數據,不同的應用應該使用不同的Redis實例存儲數據。前言中說到給兌換券加鎖,這種場景下兩個服務必須使用同一個database。

總結

redis實例默認建立了16個db,由於不支持自主進行數據庫命名所以以dbX的方式命名。默認數據庫數量可以修改配置文件的database值來設定。對於db正確的理解應爲“命名空間”,多個應用程序不應使用同一個redis不同庫,而應一個應用程序對應一個Redis實例。我們項目中的redis是使用哨兵來保持高可用,並沒有使用redis集羣,redis集羣下只有db0,不支持多db,這點需要注意。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章