redis-distributed-id-generator-start之id生成器压测的一些思考

2024-08-21 10:12

本文主要是介绍redis-distributed-id-generator-start之id生成器压测的一些思考,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 1.测试工程集成id生成器
    • 2.新建表
    • 3.测试代码
    • 4.jemeter压测结果预期
    • 5.总结

1.测试工程集成id生成器

    省略–参考之前的文章

https://mp.weixin.qq.com/s/B1vcrPVnFI1pKH7RAnPQ5g
https://blog.csdn.net/qq_34905631/article/details/138121262?spm=1001.2014.3001.5501

2.新建表

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for id_create
-- ----------------------------
DROP TABLE IF EXISTS `id_create`;
CREATE TABLE `id_create`  (`id` bigint NOT NULL COMMENT '主键',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;SET FOREIGN_KEY_CHECKS = 1;

3.测试代码

    IdCreate实体类

@Data
@TableName("id_create")
public class IdCreate implements Serializable {private static final long serialVersionUID = 8808172704142222291L;private Long id;}

    IdCreateMapper类

package xxxx.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dy.corporate.member.entity.IdCreate;import java.util.Collection;public interface IdCreateMapper extends BaseMapper<IdCreate> {/*** 批量插入 仅适用于mysql** @param entityList 实体列表* @return 影响行数*/Integer insertBatchSomeColumn(Collection<IdCreate> entityList);}

    TestController类

@RestController
@RequestMapping("/testId")
public class TestController {@Autowiredprivate ZlfRedisIdByScripts1Service zlfRedisIdByScripts1Service;private volatile Boolean flag = Boolean.TRUE;private AtomicInteger num = new AtomicInteger(0);@GetMapping("/idCreate")public RestResponse idCreate() {log.info("=========idCreate开始==============");try {if (flag) {IdCreate idCreate = new IdCreate();GeneratorIdDto dto = new GeneratorIdDto();dto.setApplicationName("t_id1");dto.setTabName("id_create");dto.setLength(16);   idCreate.setId(zlfRedisIdByScripts1Service.generatorIdByLength(dto));synchronized (idCreates) {idCreates.add(idCreate);log.info("=========idCreate加入队列完成==============num:{}", num.incrementAndGet());if (CollectionUtil.isNotEmpty(idCreates) && num.get() == 100000) {Integer i = idCreateMapper.insertBatchSomeColumn(idCreates);log.info("=========idCreate数据插入完成==============idCreates.size:{}", idCreates.size());flag = Boolean.FALSE;Thread.sleep(10 * 1000);if (i > 0) {//清空idCreatesidCreates.clear();log.info("=========idCreate====idCreates清空完毕==========");}return RestResponse.success("已插入100000成功");}}return RestResponse.success("id生成中");}} catch (Exception e) {e.printStackTrace();log.error("异常:{}", e.getMessage());return RestResponse.fail(e.getMessage());}log.info("=========idCreate====id生成完成==========");return RestResponse.success("id生成完成");}}

4.jemeter压测结果预期

    使用jemeter新建一个线程组,线程数设置1000,循环次数100次,然后多执行几次,直达请求100000(10w)次之后,使用mybatisPlus的sql注入器批量插入100000(10w)条数据到id_create表中,没有出现id重复,导致主键冲突而插入失败的情况,10w数据全部入库。

5.总结

    如果jemeter的线程设置过多的话,会出现超时连接被拒绝的问题,所以线程数需要设置少一点,之前我压测的时候也遇到这个问题,之前的文章有提到的,可以去看之前的文章,本文主要是想验证使用 redis-distributed-id-generator-start并发下生成的id会不会有重复,插入数据库导致id主键冲突,验证结果是不会的,虽然 redis-distributed-id-generator-start的代码里面使用了如下代码:

 private volatile Integer index = 0;int idx = index++ % rps.size();

    i++是线程不安全的,但是在 redis-distributed-id-generator-start里面即使是线程不安全但是最终取模的值就0,1,2选择节点也是随机的,可以达到了随机的效果,及时是不同线程同同时选到了一个节点上执行,luna脚本只能给一个线程生成id,另外一个线程生成失败之后有重试机制,会重新去随机选择节点生成id,但是还是有可能重试次数都用完了也没有生成id,但是经过上面的压测,基本上是没有出现这种情况的,累计10w数据全部插入数据库,没有出现主键冲突的情况,所以该项目还是非常666的,只不过压测的时候redis的连接满了,导致连接redis超时了,可以配置优化redis的连接参数设置大一点,这样一个redis的节点可以有更多的连接可以用,那么单节点的吞吐量将会大大提高,可以使用master-v2版本来集成测试的,可以将index++优化成使用AtomicInteger,从并发的角度index++不是线程安全的,但是根据编程严谨性上讲,这个index++是个小问题的,但是不会导致id生成重复出现,这几天思考了下单列模式(单列安全的工具类)、spring单列,有的时候是不用考虑单列是否安全,只要单列调用的方法是封闭的,使用的是内部局部的变量是安全的,java的JMM内存模型来讲,堆、方法区这两个是线程公共且共享的,但是局部变量,方法调用是在栈上,栈、本地栈、程序计数器是线程私有,所以有的时候还是需要考虑单例的线程安全性,如果单例调用的方法使用了外部全局静态、非静态变量(不管是否加了volatile关键字)是线程不安全的,除该全局变量本身具备线程安全的能力的实现(比如AtomicInteger等),所以在写代码的时候还是要时刻考虑是否有线程安全性的问题并加于解决(并发编程),有的时候写的代码跟我们想象的预期不是一致的,代码姿势真的非常非常的重要,姿势不对,努力白费,姿势不对,当场翻车,本次分享到此结束,希望对你有所启发和帮助,请一键三连,么么么哒!

这篇关于redis-distributed-id-generator-start之id生成器压测的一些思考的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1092868

相关文章

mysql8.0无备份通过idb文件恢复数据的方法、idb文件修复和tablespace id不一致处理

《mysql8.0无备份通过idb文件恢复数据的方法、idb文件修复和tablespaceid不一致处理》文章描述了公司服务器断电后数据库故障的过程,作者通过查看错误日志、重新初始化数据目录、恢复备... 周末突然接到一位一年多没联系的妹妹打来电话,“刘哥,快来救救我”,我脑海瞬间冒出妙瓦底,电信火苲马扁.

redis群集简单部署过程

《redis群集简单部署过程》文章介绍了Redis,一个高性能的键值存储系统,其支持多种数据结构和命令,它还讨论了Redis的服务器端架构、数据存储和获取、协议和命令、高可用性方案、缓存机制以及监控和... 目录Redis介绍1. 基本概念2. 服务器端3. 存储和获取数据4. 协议和命令5. 高可用性6.

Redis的数据过期策略和数据淘汰策略

《Redis的数据过期策略和数据淘汰策略》本文主要介绍了Redis的数据过期策略和数据淘汰策略,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录一、数据过期策略1、惰性删除2、定期删除二、数据淘汰策略1、数据淘汰策略概念2、8种数据淘汰策略

Redis存储的列表分页和检索的实现方法

《Redis存储的列表分页和检索的实现方法》在Redis中,列表(List)是一种有序的数据结构,通常用于存储一系列元素,由于列表是有序的,可以通过索引来访问元素,因此可以很方便地实现分页和检索功能,... 目录一、Redis 列表的基本操作二、分页实现三、检索实现3.1 方法 1:客户端过滤3.2 方法

Python中操作Redis的常用方法小结

《Python中操作Redis的常用方法小结》这篇文章主要为大家详细介绍了Python中操作Redis的常用方法,文中的示例代码简洁易懂,具有一定的借鉴价值,有需要的小伙伴可以了解一下... 目录安装Redis开启、关闭Redisredis数据结构redis-cli操作安装redis-py数据库连接和释放增

redis防止短信恶意调用的实现

《redis防止短信恶意调用的实现》本文主要介绍了在场景登录或注册接口中使用短信验证码时遇到的恶意调用问题,并通过使用Redis分布式锁来解决,具有一定的参考价值,感兴趣的可以了解一下... 目录1.场景2.排查3.解决方案3.1 Redis锁实现3.2 方法调用1.场景登录或注册接口中,使用短信验证码场

Redis 多规则限流和防重复提交方案实现小结

《Redis多规则限流和防重复提交方案实现小结》本文主要介绍了Redis多规则限流和防重复提交方案实现小结,包括使用String结构和Zset结构来记录用户IP的访问次数,具有一定的参考价值,感兴趣... 目录一:使用 String 结构记录固定时间段内某用户 IP 访问某接口的次数二:使用 Zset 进行

解读Redis秒杀优化方案(阻塞队列+基于Stream流的消息队列)

《解读Redis秒杀优化方案(阻塞队列+基于Stream流的消息队列)》该文章介绍了使用Redis的阻塞队列和Stream流的消息队列来优化秒杀系统的方案,通过将秒杀流程拆分为两条流水线,使用Redi... 目录Redis秒杀优化方案(阻塞队列+Stream流的消息队列)什么是消息队列?消费者组的工作方式每

Redis如何使用zset处理排行榜和计数问题

《Redis如何使用zset处理排行榜和计数问题》Redis的ZSET数据结构非常适合处理排行榜和计数问题,它可以在高并发的点赞业务中高效地管理点赞的排名,并且由于ZSET的排序特性,可以轻松实现根据... 目录Redis使用zset处理排行榜和计数业务逻辑ZSET 数据结构优化高并发的点赞操作ZSET 结

Redis的Zset类型及相关命令详细讲解

《Redis的Zset类型及相关命令详细讲解》:本文主要介绍Redis的Zset类型及相关命令的相关资料,有序集合Zset是一种Redis数据结构,它类似于集合Set,但每个元素都有一个关联的分数... 目录Zset简介ZADDZCARDZCOUNTZRANGEZREVRANGEZRANGEBYSCOREZ