人设名字生成器,微博id生成器

用户注册过程

大致流程是判断手机号码是否存在,如果不存在则追加; id生成是依赖于micro-basic-service微服务的id生成器,获得id后,用户中心服务执行用户记录的插入。

添加了事务,但并发运行此进程存在一些问题。

并发方案:

第一个问题是,id生成失败的micro-basic-service报告id生成失败。

原因)两个事务/进程同时来到步骤,如果发现table_id=10,然后进程1先执行步骤,使table_id从1递增,最终将数据更新为11; 此时,进程2执行到步骤,如果设定table_id=11,则在update rows affected=0时id生成失败。

并发模拟如下

同时执行手机号码登录,出现了一个失败一个成功的情况。

解决方案:

以和为原子,对查询进行排他锁定,使用排他锁定for update。

实际代码如下

虽然解决了因同时发生而导致的id生成失败的问题,但还有一个问题。

同时进行两个注册不会报告数据库主键生成失败的错误,但存在另一个问题:重复注册。

第二个问题:重复注册问题的关键是

select mobile . where mobile=15218621444 if! mobile { getNextId insert}两个过程同时来到步骤,发现手机号码不存在,从步骤到步骤的最后插入,由于手机号码没有唯一索引,同一手机号码的注册

通过的步骤后,进入注册逻辑。

解决方案:

如果同一手机号码同时注册,则同时只有一个过程通过步骤。

首先,在第个步骤中添加了select mobile…where mobile=15218621444 for update,但结果无效。 实验结果表明,在不存在记录的select for update中,数据库不会在锁定任何行时阻止表。

然后,我考虑了这些方案:

)1)使用锁表解决,如选择计数1)1) where 1 … for update。 虽然屏蔽了他,但表的性能不好。

)2)另一个按redis缓存锁排列。

)3)另一个最简单的是编制唯一的索引。

)4)对于第一类锁表改造,必须在冷数据中命中查询,屏蔽锁线。

运行后续业务逻辑,如selectidorderbyidasclimit 1…for update

select mobile…where mobile=15218621454;

if! 移动设备

{

插入…

}

以牺牲冷数据的性能为代价进行排他锁定。

于是我尝试了第四个方案,验证了是可行的。

实际代码如下

并发效果:

并发,成功只有一个。

总结:对于先查询后修改的场景,可以使用独占锁来保证代码段落的原子性。

就个人而言,由于多个服务间调用,服务2由id生成器生成并返回id,即使服务1的事务失败也不需要回滚服务2的事务,所以在这种情况下,不需要使用分布式事务技术

关于for update的详细情况,我整理了文章:

数据库for update角色: https://blog.csdn.net/w 786572258/article/details/117923902

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注