k码特权中关于 Redis & MySQL DB 乐观锁应用

1.【背景】


斐讯路由App 需要新增k码特权模块。

2.【需求】

1.已通过k码激活状态验证的用户可免费领取k码特权商品
2.每个用户每天只能领取一张k码特权奖品

3.【应用场景及难点分析】

1.接口数据安全性要求:

1.1 当某k码特权商品数据量为1,且高并发情况下,
1.2 如何防止超卖(即多个用户都抢到了剩余的一个商品)

2.接口性能要求:

斐讯路由App 现用户量为300w+,日活4w+,2/8原则分析(**指80%的业务量在20%的时间里完成**)。
经验可知用户使用斐讯路由App 的持续时间为12小时,
所以2/8分析后,80%的日活在20%的时间内完成。
即32000人免费领取k码特权商品要在2.4小时内完成,
换算成每秒 完成请求数即 QPS = 3.7/s 。
即每个接口响应请求时间至少要在 270ms 以内。才算是高性能。

4.问题分析:

1.读多写少

每个用户每日只能领取一个k码特权商品。即1个用户加入请求免费领取k码特权接口多次,在k码商品库存量充足的情况下,只能领取到1个商品,其余请求都应该返回“对不起,您今日已领取k码特权商品”。从这个方面来定义,其属于读多写少的问题。

2.并发量低

以斐讯路由现在日活情况为4w+的数据量来估算、接口并发能力 QPS = 3.7/s ,
属于低并发,但在k码特权模块优化程度达到一定量时,并发量是否会上升有待考察。
但总体来说属于并发量不高的场景。

也就是说k码特权问题经过模型抽象,已经变成了读多写少、并发量不大,但要保证性能,和数据安全性一致性的问题。

对于这类问题,乐观锁思想可以作为解决这类问题的指导思想。

5.乐观锁思想

网上文章对乐观锁理解的误区:


1.乐观锁是一种思想,并不是一种具体的技术实现。
2.乐观锁类似于CAS无锁编程技术(其实也加锁,只不过在cpu层面)

即当多个线程同时并发更新统一个变量,
采用先select再update的方式,select出当前变量a的副本值b,然后用新值c去更新,
更新时需要拿select 出来的变量值a的副本值b与当前非副本变量a的值做对比,
若暂存副本值b与当前变量a非副本值相同,则正常更新,
如果不同,则认为在当前线程更新之前已经有一个值将a变量更新,
则更新失败,在并发情况不大的情况下,
采用循环的方式去更新,总能更新成功,且循环更新次数不会太多。因此CAS也叫自旋锁。

6.k码特权-免费领取解决方案


1.用户每日成功领取k码特权商品次数的限制

采用redis 数据结构 String,记录用户每日免费领取成功次数。并且可以轻松使用redis 缓存的过期 (expire) 机制做每日领次数的控制),用户每日成功领取k码特权的次数次日凌晨清空。
为什么不使用数据库来进行用户成功领取k码特权商品次数的控制。当然建立好索引此问题也可以完美解决。
使用redis进行用户成功领取k码特权商品次数的控制原因有两个:

1.因为redis 纯粹的查询快,减轻数据库压力!不用每次都通过数据库二次索引,从磁盘找到目标记录并读入到内存。**
2.线上配置的redis使用量10%都不到,为了更好的利用硬件资源。**

2.用户每日成功领取k码特权次数的并发更改

从接口安全性考虑,若有用户恶意领取、那么有可能产生一个用户在一天之内领取了多个k码特权奖品,这个是业务需求所不允许的。
这里我们使用到了redis 提供的 事务(multi)与watch(乐观锁实现) 机制来控制 用户每日成功领取k码特权次数的并发更改。

watch机制:对键值进行监控,当被其他客户端改变时,
当前的客户端的所有操作将会失败,抛出错误信息。

3.用户并发更新同一k码特权商品库存、同一商品的具体某个item

上述问题,属于对竟态资源的并发修改,在接口请求并发量不大、且读多写少的情况下,采用数据库乐观锁来解决问题。

数据库乐观锁实现方式:
在竞态资源(商品)记录上添加一列,update_version,表示更新次数。
数据库乐观锁实现方式伪代码:
for(;;){
    //获取某k码商品库存,更新版本号 sql
    $getRewardStcokSql = 'select reward_stock,reward_update_version from fx_platform_reward_amount where reward_type_id = {$reward_type_id}';
    $getReardStockResult = $model->query($getRewardStcokSql);
    if(!$getReardStockResult ){
        die;
    } 
    $reward_stock = getReardStockResult['reward_stock'];
    $reward_update_version = getReardStockResult['reward_update_version'];
    //如果库存量>0
    if($reward_stock>0){
      //更新k码商品库存,版本号需要进行对比,其实本质上是不再使用数据库提供的排它锁,而将排他控制的职责交给选择某条需要更新记录的过滤条件。
        $updateRewardStockSql = 'update fx_platform_reward_amount set reward_stock = reward_stock-1 and reward_update_version = reward_update_version + 1 where reward_type_id = {$reward_type_id} reward_update_version = {$reward_update_version} ';
        $updateRewardStockResult = $model->excute($updateRewardStockSql);
    }
    //并发更新失败,表示在此用户更新商品库存之前已经有用户更新成功,需要重新尝试更新。
    if(!$updateRewardStockResult){
        continue;
    }
}

7.测试结果


7.1 并发测试,数据能保持一致性
7.2 用户免费领取k码特权商品响应时间均值为 110ms 左右,
      用户当日已领取过k码特权奖品的接口响应时间40-55ms左右。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352

推荐阅读更多精彩内容