好像挺久没有写博客了,趁着这段时间比较闲,特来总结一下在业务系统开发过程中遇到的并发问题及解决办法,希望能帮到大家 :grin:
问题复现
1. “设备Aの奇怪分身”
时间回到很久很久以前的一个深夜,那时我开发的多媒体广告播放控制系统刚刚投产上线,公司开出的第一家线下生鲜店里,几十个大大小小的多媒体硬件设备正常联网后,正由我一台一台的注册及接入到已经上线的多媒体广告播控系统中。
注册过程简述如下:
每一个设备注册到系统中后,相应的在数据库设备表中都会新增一条记录,来存储这个设备的各项信息。
本来一切都有条不紊的进行着,直到设备A的注册打破了这默契的宁静……
设备A注册完成后,我突然发现,数据库设备表中,新增了 两条 记录,而且是 两条一模一样 的记录!
我开始以为自己眼花了……
仔细一看,确确实实是新增了两条,而且连设备唯一标识(划横线,后面要考)和创建时间都一模一样!
看着屏幕,我陷入了沉思……
为什么会有两条呢?
在我的注册逻辑里,落库之前会先查一遍数据库该设备是否已存在,如果存在就更新已有的,不存在才新增。
所以我百思不得其解,按这个逻辑,第二条一模一样的数据是哪来的?
2. 真相背后的并发请求
经过一番排查及思考,我发现问题可能就出在注册请求上。
设备A在向云端发送http注册请求时,可能会同时发送多个相同请求。
云服务器当时部署在多台Docker容器上,通过查看日志发现,有两台容器同时收到了来自设备A的注册请求。
由此,我推测:
设备A同时发送了两个注册请求,这两个请求分别在同一时间打到了云端的不同容器上,按照我的注册逻辑,这两个容器接收到注册请求后,同时去查询了数据库的设备表,这时候设备表里还没有设备A的记录,所以两台容器都执行了新增的操作,因为速度很快,所以这两条新增记录在 精确到秒 的创建时间上,并没有体现出差别。
3. 并发新增的延伸
既然并发的新增操作会产生问题,那么并发的更新操作是否会有问题呢?
解决方法
解决并发新增
1. 数据库唯一索引(UNIQUE INDEX&