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

相关文章

Redis实现延迟任务的三种方法详解

《Redis实现延迟任务的三种方法详解》延迟任务(DelayedTask)是指在未来的某个时间点,执行相应的任务,本文为大家整理了三种常见的实现方法,感兴趣的小伙伴可以参考一下... 目录1.前言2.Redis如何实现延迟任务3.代码实现3.1. 过期键通知事件实现3.2. 使用ZSet实现延迟任务3.3

Redis分片集群的实现

《Redis分片集群的实现》Redis分片集群是一种将Redis数据库分散到多个节点上的方式,以提供更高的性能和可伸缩性,本文主要介绍了Redis分片集群的实现,具有一定的参考价值,感兴趣的可以了解一... 目录1. Redis Cluster的核心概念哈希槽(Hash Slots)主从复制与故障转移2.

mysql数据库重置表主键id的实现

《mysql数据库重置表主键id的实现》在我们的开发过程中,难免在做测试的时候会生成一些杂乱无章的SQL主键数据,本文主要介绍了mysql数据库重置表主键id的实现,具有一定的参考价值,感兴趣的可以了... 目录关键语法演示案例在我们的开发过程中,难免在做测试的时候会生成一些杂乱无章的SQL主键数据,当我们

Redis 中的热点键和数据倾斜示例详解

《Redis中的热点键和数据倾斜示例详解》热点键是指在Redis中被频繁访问的特定键,这些键由于其高访问频率,可能导致Redis服务器的性能问题,尤其是在高并发场景下,本文给大家介绍Redis中的热... 目录Redis 中的热点键和数据倾斜热点键(Hot Key)定义特点应对策略示例数据倾斜(Data S

redis+lua实现分布式限流的示例

《redis+lua实现分布式限流的示例》本文主要介绍了redis+lua实现分布式限流的示例,可以实现复杂的限流逻辑,如滑动窗口限流,并且避免了多步操作导致的并发问题,具有一定的参考价值,感兴趣的可... 目录为什么使用Redis+Lua实现分布式限流使用ZSET也可以实现限流,为什么选择lua的方式实现

Redis中管道操作pipeline的实现

《Redis中管道操作pipeline的实现》RedisPipeline是一种优化客户端与服务器通信的技术,通过批量发送和接收命令减少网络往返次数,提高命令执行效率,本文就来介绍一下Redis中管道操... 目录什么是pipeline场景一:我要向Redis新增大批量的数据分批处理事务( MULTI/EXE

Redis中高并发读写性能的深度解析与优化

《Redis中高并发读写性能的深度解析与优化》Redis作为一款高性能的内存数据库,广泛应用于缓存、消息队列、实时统计等场景,本文将深入探讨Redis的读写并发能力,感兴趣的小伙伴可以了解下... 目录引言一、Redis 并发能力概述1.1 Redis 的读写性能1.2 影响 Redis 并发能力的因素二、

Redis中的常用的五种数据类型详解

《Redis中的常用的五种数据类型详解》:本文主要介绍Redis中的常用的五种数据类型详解,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Redis常用的五种数据类型一、字符串(String)简介常用命令应用场景二、哈希(Hash)简介常用命令应用场景三、列表(L

Redis解决缓存击穿问题的两种方法

《Redis解决缓存击穿问题的两种方法》缓存击穿问题也叫热点Key问题,就是⼀个被高并发访问并且缓存重建业务较复杂的key突然失效了,无数的请求访问会在瞬间给数据库带来巨大的冲击,本文给大家介绍了Re... 目录引言解决办法互斥锁(强一致,性能差)逻辑过期(高可用,性能优)设计逻辑过期时间引言缓存击穿:给

Redis中如何实现商品秒杀

《Redis中如何实现商品秒杀》:本文主要介绍Redis中如何实现商品秒杀问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录技术栈功能实现步骤步骤一:准备商品库存数据步骤二:实现商品秒杀步骤三:优化Redis性能技术讲解Redis的List类型Redis的Set