首頁  >  問答  >  主體

抽奖活动计数 redis vs mysql

业务:

抽奖活动 限制每天抽奖次数 每个用户每天只能抽奖3次
同时若有中奖的话更新奖品中奖数和奖品库存数

方案一:
使用mysql(ssd硬盘) 如下所示

#更新用户抽奖次数
select * from draw_count;
+----+---------+------------+-------+
| id | user_id | draw_date  | count |
+----+---------+------------+-------+
|  1 |       1 | 2016-03-12 |     3 |
+----+---------+------------+-------+
#显式指定count<3 如果更新count失败 表示已抽完3次 使用这种方式也可以应对同一用户并发超抽的情况。
update draw_count set count=count+1 where user_id = 1 and draw_date=current_date and count<3;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 0  Changed: 0  Warnings: 0


#中奖后更新奖品中奖数和库存
select * from award_count;
+----+----------+-----------+-------+
| id | award_id | win_count | stock |
+----+----------+-----------+-------+
|  1 |        1 |         0 |   100 |
+----+----------+-----------+-------+
#显式指定stock>0 避免并发超抽的情况 只有更新成功了 才表示成功中奖
update award_count set win_count = win_count+1 , stock = stock-1 where award_id = 1 and stock>0;
Query OK, 1 row affected (0.06 sec)
Rows matched: 1  Changed: 1  Warnings: 0

方案二:
使用redis 如下所示

#更新用户抽奖次数
127.0.0.1:6379> incr 1_20160312
(integer) 1
127.0.0.1:6379> incr 1_20160312
(integer) 2
127.0.0.1:6379> incr 1_20160312
(integer) 3
127.0.0.1:6379> get 1_20160312
"3"

#更新奖品中奖数和库存
127.0.0.1:6379> incr 1_win_count
(integer) 1

127.0.0.1:6379> decr 1_stock
(integer) 99

使用redis来限制并发超抽的情况

好像面对上述场景大家想到的都是使用redis, 但使用mysql的劣势在哪呢?尤其当使用的是ssd硬盘的mysql

巴扎黑巴扎黑2765 天前422

全部回覆(2)我來回復

  • 迷茫

    迷茫2017-04-17 13:57:21

    看具體情況,對並發比較大的情況下redis會比較有優勢,而且incr系列api又是保證原子性操作。 mysql速度會稍微差些,ssd也不會有記憶體快。對於這種有key/value操作顯然nosql產品更有優勢。

    回覆
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-17 13:57:21

    使用redis會有一個問題,那就是到最後你的商品數量剩餘量可能是小於0的,即因為redis只能保證每個操作的原子性,如果你需要判斷商品數量是否大於0,然後再決定是否減少餘量,這樣redis是沒法保證原子性的,並發就會導致餘量小於0,但是並不影響業務的正確性,因為你可以透過decr的回傳值是否>=0來判斷發獎成功與否。


    MySQL畢竟是檔案存儲,肯定沒辦法跟內存比,這種情況下一般方案是redis+mysql,這種資料不落DB誰放心呢。

    回覆
    0
  • 取消回覆