1。1。
購物車常見實現方式
購物車是任何一個電商專案都會使用到的功能,面試的時候也經常問到,傳統的做法是使用關係型資料庫,比如mysql,建立一個cat購物車表,把相關的購物車產品資訊都放到資料庫裡面。
CREATE TABLE goods_shopcar (id int(4) NOT NULL ,uid int(10) NULL ,goods_id int(10) NULL ,number int(10) NULL ,status tinyint(4) NULL ,create_time int(10) NULL ,update_time int(10) NULL ,PRIMARY KEY (id));
這樣的設計在功能完全沒問題,但在實際使用中,由於購物車的資料量太大,而且修改頻繁,會導致資料庫的壓力增加,所以在正式專案開發中,一般不會直接使用關係型資料庫來儲存購物車資訊。
既然不用關係型資料庫,但就從非關係型資料庫裡面做選擇了,很多的架構師會選擇使用mongodb 存購物車的資料,這也完全可以,mongodb有非常豐富的查詢API,效能也比傳統關係型資料庫要好,使用mongodb確實是個不錯的選擇。
但比起使用mongodb,有部分公司也會使用redis來存放購物車的資訊,比起mongdb的效能,redis的效能要來得更好。
在這就來談論下使用redis來完成購物車的思路。
1。2。
開啟持久化
購物車的資料,既然不存在關係型資料庫中,使用redis儲存也不能讓資料丟失,那redis必須開啟持久化,這樣哪怕redis重啟資料也不至於丟失。
Redis有兩種持久化機制,一種叫rdb,一種叫aof。
rdb也叫映象檔案,存放的是某個時刻redis記憶體資料的一個映象
aof就是append only file的簡寫,裡面存放的是日誌檔案,準確的來說是存放RESP的指令日誌,這裡RESP指令並不是這次的重點,這裡不做討論。
首先,RDB預設是開啟的,在Redis配置檔案裡面,關於RDB的配置如下
save 900 1:表示900 秒內如果至少有 1 個 key 的值變化,則儲存save 300 10:表示300 秒內如果至少有 10 個 key 的值變化,則儲存save 60 10000:表示60 秒內如果至少有 10000 個 key 的值變化,則儲存
預設的配置最少是60秒並且有10000個key發生變化才會重新整理一次映象,這樣如果在時間沒到60秒,這個時候redis意外宕機,在這個時間段的資料都會丟失
你可能會想,是否可以增加一條配置
save 1 1:表示1 秒內如果至少有 1 個 key 的值變化,則儲存
這樣資料視乎就不會丟失,但這肯定是不行的,每一秒都對redis記憶體的所有資料都寫入一次磁碟變成映象檔案,這樣對效能影響非常大。
為了防止資料丟失,光從rdb上下手還是不行,預設aof並沒開啟,應該開啟aof日誌檔案,這時候得修改配置檔案,增加aof的相關配置
appendonly yes
開啟了aof日誌,丟失資料的可能性就減少很多了。
1。3。
業務分析
以京東的購物車為例,按業務分析,需要完成如下功能:
全選功能-獲取所有該使用者的所有購物車商品
商品數量-購物車圖示上要顯示購物車裡商品的總數
刪除-要能移除購物車裡某個商品
增加或減少某個商品的數量
1。4。
資料結構選擇
Redis常用有5種資料型別分別為string,hash,list,set,zset,在這個案例裡面我們選擇使用hash來完成這個購物車功能
先對hash這種資料型別的常用命令進行介紹
redis中hash的新增命令hset,如果key不存在,建立key,存在,則覆蓋原有值
redis 127。0。0。1:6379>hset myhash name enjoy ——給key為myset的鍵值設定鍵為name值為enjoy
redis中hash的檢視命令hget
redis 127。0。0。1:6379>hget myhash name ——輸出: “enjoy”,獲取key為myset,鍵為name的valueredis 127。0。0。1:6379>hset myhash name xiangxue ——覆蓋原有值,值改為xiangxue替換 redis 127。0。0。1:6379>hget myhash name ——-輸出:“xiangxue”
redis中hash的獲取key包含的field數量的命令hlen
redis 127。0。0。1:6379>hset myhash age 20 ——- 設定key為 myhash 鍵為age的value=20redis 127。0。0。1:6379>hlen myhash ——-輸出為2,key為myhash的field數量為2
redis中判斷指定key中指定field是否存在的命令hexists,存在返回1,不存在返回0
redis 127。0。0。1:6379>hexists myhash name ——-返回1,說明存在redis 127。0。0。1:6379>hexists myhash name1 ——-返回0,說明不存在
redis中hash刪除命令hdel,刪除一個或多個指定的欄位
redis 127。0。0。1:6379>hset myhash sex boy ——新增資料redis 127。0。0。1:6379>hset myhash likes sports ——新增資料redis 127。0。0。1:6379>hdel myhash likes ——刪除單個數據,filed為likes 的資料
redis中hash如果key或field不存在插入有效,否則不採取操作的命令hsetnx
redis 127。0。0。1:6379>hsetnx myhash sex boy ——-設定myhash,field為sex的value為boy,不成功返回0,因為原來存在sex這個欄位並且有值redis 127。0。0。1:6379>hget myhash sex ——輸出“boy”
redis中hash中的value為數值時操作增減的命令hincrby
redis 127。0。0。1:6379>del myhash ——-刪除該鍵redis 127。0。0。1:6379>hset myhash age 20 ——-設定key為myhash的鍵為age值為20redis 127。0。0。1:6379>hincrby myhash age 10 ——-給key為myhash,鍵為age的值加10,輸出結果為30redis 127。0。0。1:6379>hincrby myhash age -10 ——-給key為myhash,鍵為age的值減去10,輸出結果為20
批次新增key/value的命令hmset
redis 127。0。0。1:6379>del myhash ——刪除該鍵redis 127。0。0。1:6379>hmset myhash name enjoy age 20 issingle yes ——給key為myhash的hash新增name=enjoy,age=20,issingle=yes 的多個鍵值
批次獲取key/value的命令hmget
redis 127。0。0。1:6379>hmget myhash name age issingle ——輸出結果為:enjoy 20 yes
根據myhash鍵獲取所有的欄位及value的命令hgetall
redis 127。0。0。1:6379>hgetall myhash ——輸出結果為:name age issingle enjoy 20 yes
獲取所有的field的命令hkeys
redis 127。0。0。1:6379>hkeys myhash ——-輸出結果為:name age issingle
獲取所有欄位的值的命令hvals
redis 127。0。0。1:6379>hvals myhash ——輸出結果為:enjoy 20 yes
1。5。
業務設計
在購物車的場景下,既然選擇使用hash來完成,可以總體規劃如下
以使用者ID作為key
以商品id作為field
以商品的數量作為value
1。5。1。
增加購物車商品
假設現在使用者ID為1001,這使用者往購物車放3個商品,產品的ID為10021,10025,10079,對應的指令應該為
hset cart:1001 10021 1hset cart:1001 10025 1hset cart:1001 10079 1
1。5。2。
全選功能
全選功能-獲取所有該使用者的所有購物車商品,這個就非常好完成了,使用hgetall 指令就好。
hgetall cart:1001 這樣就能把使用者1001的購物車裡面所有商品列出來。
1。5。3。
商品數量
商品數量-購物車圖示上要顯示購物車裡商品的總數,這樣也不難,使用hlen指令就好。
hlen cart:1001 顯示3,顯示的是購物車的商品數量。
1。5。4。
刪除商品
刪除-要能移除購物車裡某個商品。
hdel cart:1001 10079 刪除了購物車裡商品ID為10079的商品。
1。5。5。
增加商品
增加或減少某個商品的數量。
hincrby cart:1001 10021 1 透過這樣指令,使購物車產品id為10021的商品數量增加了1。
這樣設計,的購物車,效能是很好的,而且也減少了資料庫的壓力,在真實的專案中可以考慮這樣使用。
問題:
redis的持久化機制有哪些?
解答:
Redis支援aof,rdb兩種持久化機制,預設使用的是rdb,aof需要修改配置檔案開啟。rdb也叫映象檔案,存放的是某個時刻redis記憶體資料的一個映象。aof就是append only file的簡寫,裡面存放的是日誌檔案,準確的來說是存放RESP的指令日誌,每一條對 redis的操作命令都儲存在裡面。