实习过程中碰到的幂等性与StringBuilder与分布式锁等问题

592 阅读4分钟

前言

上一次迭代中的bug修复

这段时间也是比较忙的,先是开一个用例评审对上一次迭代中各个模块存在的bug做了一个汇总,令我惊呆的是测试找bug的细致程度到了新开一个页面去找,这样的话有些逻辑判断我是没有做的,我负责的是知识目录树模块的接口,总体bug不多,就是有一些比较刁钻的bug,有个不好实现的功能就留给leader和产品扯皮去了(之前差点吵起来了,哈哈哈哈)。

这次迭代的需求

之后我们开了个技术评审的会,分配了一下需求,我负责的有考试加人模块和测验模块中的部分和一个修改状态的定时任务的接口提供,这次的需求就碰到了很多中间件(redis,redisson,mongo,mq等等),这个过程中我还是学到了很多。

微信图片_20240729111233.jpg

考试加人接口的幂等性

因为我后面还要提供一个对于后续加人的补充的一个消息监听,所以这个时候我就想到了对于重复的消息该怎样保证只添加一次即保证接口的幂等性,我刚开始想的是做一个逻辑判断(一种乐观锁的思想),对于重复的人不做添加,后面和leader一说,leader说数据库已经实现了幂等性,接下来让我一一道来。

在考试加人类型表和考试人员表中都有一个加了唯一索引的字段unique_index,它是由 exam_id,agency_id,add_type,add_type_id拼接而成的(这里就是考试加人可以按多种方式加人),当删除操作的时候除了将is_deleted改为1做一个逻辑删除之外,还要在unique_index后面拼接一个主键id,后续按这种类型再加进来的时候,就满足了unique_index的唯一,也同时满足了幂等性,对于消息的重复消费也插入不了数据库了,而且索引还提高的查询效率,两全其美。

下面对比一下两种接口幂等性实现的优缺点:

数据库层面维护一个具有唯一索引的字段

优点:1.避免了在应用层进行复杂的逻辑判断。 2.数据库的唯一索引操作通常具有原子性,可以有效防止并发操作导致的数据不一致问题。

缺点:1.带来了额外的性能开销。 2.当数据库层出现问题,就会影响幂等性的保证,这个时候就要保证数据库的高可用了(集群)。

接口中逻辑判断实现的幂等性:

优点:1.灵活控制。 2.减少数据库的压力,性能较好。

缺点:1.增加了逻辑复杂度。 2.在高并发场景下,需要额外的并发控制机制。

测验相关接口的StringBuilder与分布式锁问题

对于测验的添加与修改等接口都要考虑到并发安全问题,leader叫我通过封装好的redissonUtil工具类来加分布式锁,只能说都封装好了就调个方法就好了很简单的哈哈哈哈。

在拼接key的时候我是直接通过+的方式拼接多个字符串(这里补充一下只要不是循环拼接,编译器会优化那些字符串常量的+的拼接),leader说这样性能低,每一次+都会创建一个新的String对象,我突然想起了我背的八股文(String是不可变类型,StringBuilder和StringBuffer是可变类型),只能说是会背不会用哈。String的+的拼接产生的额外的临时对象会增加垃圾回收的负担,因此让我用StringBuilder的append方法来拼接,这样避免了不必要的内存分配,提高了性能。

相比StringBuilder,StringBuffer是线程安全的,他所有的方法都加了synchronized锁,这样带来的安全性当然也会导致性能下降。 后面再通过redissonUtil加分布式锁来确保同一时间只有一个请求能够执行测验的创建与修改,避免并发问题。

后续

这次迭代就剩个消息监听的需求,我没事的时候会看看他们写好的代码学习学习,之后把看到的精华总结总结,我们公司还举办了一个活动,整个研发部门分组,每组利用字节的Coze搭建bot然后实现一个简单的前后端项目,还有其他任务,有小金豆,过几天就开始了。之后下次迭代听leader说是ai出题模块的,狠狠期待了,孩子们!!!

u=2657241801,3143797527&fm=253&fmt=auto&app=120&f=JPEG.webp