从0开始,从应对”恶意发包“展开的分布式锁学习
投入Java开发工作半年期间,编码内容以产品需求为准,以产品业务为中心,由于紧密的开发周期和基于工作实用性的考虑,没有尝试去挖掘前沿的知识学习。
这一周的C#服务端开发,在YQ循循善诱中,业务环境不断变化,思考的层面不断提升,代码不断重构,学习了很多。
一方面,有周期地整理所学的知识的必要,用自己的理解来产出和记录,另一方面,也为了锻炼自己持之以恒的品质和语言归纳能力。
第一周:C#语法 + MVC练习
第二周:外务府练习
第三周:外务府重构+风云棋盘练习(自己设计表结构)
第四周:风云棋盘重构
前四周的练习难度不大,内容也比较枯燥。重点写第五周开始至今的开发学习。
第五周:YQ让我模拟Http的GET请求,尝试多次服务器请求,思考存在什么问题。
一、排行榜奖励重复领取
需求:点击排行榜,出现排行前100的玩家列表,底部出现”我的排名“,和领取奖励按钮。
预期:点击领取奖励,正常获得相应道具。
实际:模拟恶意发包,向服务端发起领取奖励请求(50次),出现重复领取奖励的情况。
分析:(实际上是多次,这里以两次为例)当两次http请求间隔小于(判断是否已经领取过奖励的)代码执行所需时间时,两次请求都将获得尚未领取的状态值,假设为0。
原因:1.多进程场景下,出现同一行代码被先后执行多次是很正常的,多个进程意味着存在多份服务端代码同时运行,此时数据库的数据同时应对多个进程,也将会导致重复领取。
2.同理,而单进程场景下,多线程的情况下,也可能存在代码被先后执行多次。
3.因此,不对玩家的领取状态值进行读写控制,将会出现丢失数据。
解决过程:1.YQ先让我为每个用户加锁,用户请求领取时,需判断锁表中不存在用户锁才能进行操作,如果不存在,则往锁表插入用户锁(每个用户唯一)数据,即同一时刻,有一个用户在访问数据库,则其他用户请求失效。
2.用程序内置锁(lock关键字或者using)对代码进行同步处理,单进程多线程场景下问题解决。
3.接着YQ让我做触发全服成就的业务,发现多进程并发场景下,数据丢失问题仍然存在。
3.接着YM帮我分析原因,程序内置锁只能解决单进程的问题,如上述原因1,多进程情况下,不可避免地会出现问题。
4.YQ提出分布式锁的概念,即多个客户端,访问服务器集群(多个),但服务器集群访问的数据库是同一个。因此要用数据库来控制服务器的代码执行。
5.因此引入分布式锁,在全服成就的场景下,全部服务器的全部玩家共用一个锁,当某个用户触发了全服成就,全服成就表的进度顺利+1后,释放锁。
6.分布式锁的运行机制:service/action往任务流水表中插数据,并且调用异步任务线程处理任务,任务流水表的读写代码用全服锁控制。

浙公网安备 33010602011771号