当前位置: 首页 > 后端技术 > PHP

PHPer每月工作总结:搭建一个抽奖工具

时间:2023-03-30 03:21:52 PHP

前言目标是每个月写一篇文章,对编程开发的基础知识做一个学习总结。这个月的计划本来是做一个基础数据结构的沉淀,但是,但是,但是...这个月的状态是工作,工作...既然如此,那么我们来总结一下这个月的工作吧。工作内容推广活动抽奖工具具有以下功能:根据不同的订单金额抽奖,可根据不同的抽奖次数设置最大订单金额限额抽奖,可根据不同的抽奖次数设置积分消费限额抽奖时间段,可以设置积分消耗限额来构建看到上面的需求,很明显我们会想到策略模式,制定三个不同的策略实体类:彩票开奖策略:LotteryOrderStrategy彩票开奖策略由次数:LotteryTimesStrategy时间段开奖策略:LotteryTimeScopeStrategy建立了三个具体的策略实体类后,由于不同的开奖策略其实有很多相似的行为,所以我们开始抽象,最终整个开奖行为如下:活动参与条件验证:检查【抽象方法】读取规则信息:getRule【具体方法】匹配合规规则区间:getNodeByRule【抽象方法】活动参与人数验证:checkTimes【具体方法】活动规则限额验证:checkJoinLimit【抽象方法】消耗点数:consumePoints【抽象方法】读取规则对应的所有奖品:getPrize[具体方法]抽奖:draw[具体方法]组装奖品信息:packagePrizeInfo[具体方法]接下来创建一个抽象类:LotteryAbstract。抽象完成后:逻辑相同:可以直接继承使用不同的彩票实体类逻辑不同:可以具体实现不同的彩票实体类具体抽象类如下:abstractclassLotteryAbstract{abstractprotectedfunctioncheck();protectedfunctiongetRule(){#code...}abstractprotectedfunctiongetNodeByRule();受保护函数checkTimes(){#code...}抽象受保护函数checkJoinLimit();抽象保护函数consumePoints();protectedfunctiongetPrize(){#代码...}protectedfunctiondraw(){#code...}protectedfunctionpackagePrizeInfo(){#code...}}然后我们发现不同开奖策略的开奖过程基本相同,于是我们想到了“Template”模式”,我们对抽象类做了一些小的调整,我们在抽象类中实现了抽奖算法的调用过程,最后抽象类构成了抽奖类的模板。将来,我们将添加一个新的抽象方法。我们只需要实现抽奖模板的抽象方法即可。改动后的抽象类如下:abstractclassLotteryAbstract{/***彩票算法*/publicfunctionrun(){$this->check();$this->getRule();$this->getNodeByRule();$this->checkTimes();$this->checkJoinLimit();$this->consumePoints();$this->getPrize();$this->draw();$this->packagePrizeInfo();}抽象保护函数check();protectedfunctiongetRule(){#code...}abstractprotectedfunctiongetNodeByRule();受保护函数checkTimes(){#code...}抽象受保护函数checkJoinLimit();抽象保护函数consumePoints();protectedfunctiongetPrize(){#code...}protectedfunctiondraw(){#code...}protectedfunctionpackagePrizeInfo(){#code...}}并发建模完成后,仍然存在并发问题:更改同时获得的奖品数量的问题。当然你可能会想到加锁,让并发进程变成串行进程,这样就不会有问题了。一种是使用mysql的悲观锁(forupdate),但是考虑到去彩票的过程是用在类似秒杀的场景,所以考虑使用redis的悲观锁来实现,毕竟io内存的性能比磁盘高很多,所以第一个方案如下:redis悲观锁localab-c100-n1000 压测正常。然后上线的时候就出问题了。同时大量的redis操作远超之前的峰值。然后第二个方案出来了。如果拿不到锁,休眠5毫秒,降低锁的频率。失败的);上面的方案有效的降低了峰值,但是造成了499个请求,然后第三个方案就出来了,具体方案如下:由于redis是单线程的,利用redis的decr自减来保证奖品库存的准确性活动开始前,将奖品库存注入redis,定时将库存同步到mysql(减少直接从mysql减少库存的主库压力)。通过该方案,基本减轻了redis和mysql主库的压力。问题下面说一下这段时间工作遇到的一些问题:个人问题:redis悲观锁使用不当,抢锁失败不休眠,导致在线redis瞬间大量操作(本地没发现问题压力测试),后期会深入研究这方面,从头到尾没有认真的codereview(项目开发时间太紧迫)项目进度混乱:每年定期举办活动,但只有预留5天开发时间接口文档:老掉牙的wiki文档,没有返回值的例子,也没有返回值的类型说明。前后端开发成本增加,效率低下。前端依赖:前端严重依赖后端数据进行调试和测试效率低:纯手工测试,缺乏一些基础工具的使用后台工程项目代码效率低:基本不具备代码复用能力的代码,组织混乱使用环境:目前我们开发测试灰度环境,每次使用前都是靠“喊”。经常会出现代码被别人改写的问题。svn问题。同事本地代码丢失代码发布的分支。发布与主干合并,导致线上紧急修复分支被代码发布阻塞的分支,往往会导致忘记合并回主干。每次发布前,都需要去专门的在线对码机进行对码。解决方案提出问题,当然要给出相应的解决方案:个人问题:继续深入学习基础知识。目前对于nginx、linux、redis、mysql、mongo还是要好好学习的。质量代码审查是必须的。项目排期混乱:希望能从产品和上级反馈中挖掘原因,避免和减少同样事情的发生。工具的使用从当下做起。前端依赖:推前端同事断点调试和api mock测试效率低下:至少提倡目前使用简单代理工具效率低下后台工程项目代码:有可能提倡内部使用yii2到开发后台,个人感觉开发后台gii还是挺高效的。各种环境下使用:有空写一个简单的页面,用环境对应的机器的checkbox来选择。一目了然,完全避免了以前的问题。代码,为避免代码丢失和紧急修复分支的问题,采用git工作流的热补丁随时上线。git工作流的工作流程可以避免我们现在的svn代码经常忘记合并到主干的问题,只要git本地diff分支代码就可以了 提高效率体验在写代码之前,一定要尽量想清楚要做什么可能在写代码之前,进行必要的抽象过程,这样你平时就可以写出易于阅读和扩展的代码(不过,不务正业的代码就是耍流氓,哈哈~)codereview是必不可少的,养成习惯吧慢慢来,骚年压测,压测我们写的代码,可以简单的用ab,攻城项目完成后的总结和沉淀