乐观锁,大多是基于数据版本( version)记录机制实现的。什么是数据版本呢?就是在数据库表中新增一个int类型字段version,每当读取数据对象时候,一并带上version读出,每当更新数据对象的时候,将version+1,然后将提交过来的数据版本version和数据库表中的version做比较,如果提交过来的version大于数据库表中的version,那么进行更新操作,否则,认为提交过来的数据已过期。这样就能保证数据一致性。
在银行账户系统设计中,这种情况最为常见,当某个操作员读取用户银行账户数据,并在读出的用户数据的基础上更改用户账户余额,假如整个操作过程中(从操作员读出数据,开始修改直到提交修改结果的全过程,甚至还包括操作员中途等待的时间)数据库记录始终处于加锁状态,当面对成千上万高并发的情况有会是如何?而分布式锁在此场景并不适用,这时候乐观锁就派上用场了。
假设张三在某银行账户中有1000元RMB,那么某银行账户信息表对应的version值为1,余额balance值为1000。
Step1 张三没生活费了,于是去ATM取款机中取钱,此时ATM取款机读取到了账户信息 张三 version =1 balance=1000,张三取款500元,那么余额就是
500=1000-500元
Step2 正当张三取款的过程中,某银行柜员也读取了张三的账户信息(version=1,balance=1000),并(假设卡年费是柜员人工扣)扣除银行卡管理年费10元(1000-10),
Step3 ATM取款机会version=version+1,并把余额500元提交给后台数据库,后台将提交过来的数据(version=2)和数据库表中的version(version=1)比对,发现提交过来的数据大于当前数据库表中的版本号version,则进行取款指令,这样张三就从ATM取款机中取出了500元。
Step4 银行柜员也操作完成,使version版本加1(version=2),并把余额balance设置为990元,并试图发送给后台处理,但是一比对提交过来的version和数据库表中的version相等,不满足条件,于是返回数据过期给前台,那么柜员重新查询一次数据获取到新的数据才能进行下一次成功的操作。
假设说银行柜员这个提交操作不使用乐观锁保证数据同步,那么玩笑开大了,难道扣了年费10元,取款500元,银行卡钱还多起来,真是天大的笑话(扯淡,本来应该是余额490元,而变成了990元,这不是给我送500元么?)。
领取专属 10元无门槛券
私享最新 技术干货