《阿里巴巴Java开发手册》条例解读(一)-阿里云开发者社区

开发者社区> 数据库> 正文

《阿里巴巴Java开发手册》条例解读(一)

简介: 《阿里Java开发规范》应该是众多程序猿多年来,在使用Java的过程中,根据踩过的雷趟过的坑,总结出来的“血的教训”或“踩坑手册”。但就像《葵花宝典》,即便是读过一百遍也成功自宫,也不见得能马上能成为武林高手,因为没练过。

《阿里Java开发规范》应该是众多程序猿多年来,在使用Java的过程中,根据踩过的雷趟过的坑,总结出来的“血的教训”或“踩坑手册”。但就像《葵花宝典》,即便是读过一百遍也成功自宫,也不见得能马上能成为武林高手,因为没练过。搞软件工程就像练武功需要实操,没有实战经验很难成为高手。评判是不是高手的标准是什么?如果仅从软件工程的角度看,很重要的一点就是交付的软件在各种高业务压力、异常情况下压不垮、跑不死、业务正常运行。而新手往往很难做出这样健壮的系统,因为健壮的系统需要规避无数的雷和坑。如果不知道这些可能存在的这样或那样的坑或雷,自然谈不上填上这些坑、避开这些雷。而且,就算在书本或规范上看过这些“宝典”,也知道这些坑的存在,但没有跌坑踩雷的亲身经历,在碰到跌坑踩雷的场景时,也可能忽略而忘记“宝典”中的“金玉良言”。为什么会忽略、为什么会不够重视,因为你没有真的痛过。痛过才能成熟,相信我,这是真的^o^
所以,聊一聊为什么会有这样的开发条例,如果不按规范来可能出现哪些问题,了解背后的故事,可能比读一百遍规范来得更有效果。

> 【6.11】【强制】并发修改同一记录时,避免更新丢失,需要加锁。要么在应用层加锁,要么在缓存 加锁,要么在数据库层使用乐观锁,使用 version 作为更新依据”。

到底什么是“更新丢失”呢?到底会导致多严重的问题?初看这个描述,说实话一点感觉没有,如果你没有碰到过这类并发问题导致的严重事故,看完这条规范后,大概率情况下该踩的雷还得踩。
从我碰到的出镜率比较高的问题开始,分享一下开发系统中遇到过的场景。

在IOT场景下,不同的终端设备需要分配不同的物联网卡进行数据通信,最基本的限制就是一张卡只能分给一个设备。如果,一张卡分给多个设备将会导致卡被交替使用,不同的终端使用同一张卡交替上线下线,进一步导致运营商停卡和客户投诉。即便是少量的一卡多分在业务上也是很难接受的。而分卡服务必定需要部署多个服务节点,单个节点肯定无法满足大业务量需要,并发/并行地选中并占用同一张卡是必然会出现的(并发/并行处理的概念请自修)。由于大量终端请求到达服务端后,会被后端无状态服务的多个节点处理,不同的终端分卡请求会落在不同的节点上,这时不同的终端可能会被不同的服务节点分配同一张卡。比如节点A的终端TA请求占卡1,表示为1-TA,和节点B的终端请求TB占卡1,表示为1-TB。如果这2个不同节点上的请求请求以前后相差1毫秒的时间更新了数据库,导致的结果是TA分到了卡1,并返回给终端,紧接着TB也被认为分到了卡1并返回给终端,一卡多分。但系统中的最终记录是1-TB,终端TB占有卡1。可一毫秒前从业务的角度看是终端TA占的卡1。于是在接下的一段时间,终端TA和终端TB轮流使用用卡1,卡1会被不断地上线又踢下线又上线,循环反复。如下图
_

所以“更新丢失”更准确的描述是“更新覆盖”,当一个进程修改某条业务数据后会被另一个完全不知情的进程覆盖数据,导致在整个业务层面数据状态的不一致,因此“需要加锁”。但是规范中并没有明确应该怎么选择在什么样的场景下使用什么样的锁。
为了应用服务能够平滑横向扩容,没有对业务状态有特定要求的场景,我们通常会把应用设计成无状态应用,当业务压力增大只需要通过增加应用服务节点就能满足提升处理能力的要求。对于上述占卡的应用场景,系统选择多应用节点并行处理分卡请求,来提升系统吞吐量。如果仅仅选择在单应用节点上加锁,不能解决多节点多进程并行处理导致的数据冲突。但如果选用缓存(Redis)锁,把卡资源作为锁对象,则需要将数据库中的记录和缓存做同步,本身就涉及数据同步和数据一致性问题。在需要对大量数据加锁或长时间加锁时,不建议优先考虑使用悲观锁,因为一次分卡请求可能需要读取大量的卡资源做排序、过滤,锁住大量的卡会极大降低并发吞吐量。更好的方式是使用乐观锁,并且是直接在数据库层使用乐观锁,用version(UUID)作为更新依据。更新SQL ,UPDATE table XXX where version = UUID。(数据库乐观锁的原理请自修)。只是在选卡和占卡时,需要做一些功课来降低冲突的可能性,但能保证在任何时候卡数据不被过期(脏)数据覆盖。当然,这种一致性只是在服务端达成的一致性。终端和服务端对占用同一张卡达成的一致性问题,需要另外的分布式一致性方案才能解决。
_

版权声明:本文首发在云栖社区,遵循云栖社区版权声明:本文内容由互联网用户自发贡献,版权归用户作者所有,云栖社区不为本文内容承担相关法律责任。云栖社区已升级为阿里云开发者社区。如果您发现本文中有涉嫌抄袭的内容,欢迎发送邮件至:developer2020@service.aliyun.com 进行举报,并提供相关证据,一经查实,阿里云开发者社区将协助删除涉嫌侵权内容。

分享:
数据库
使用钉钉扫一扫加入圈子
+ 订阅

分享数据库前沿,解构实战干货,推动数据库技术变革

其他文章