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 的 SUBSCRIBE命令详解

《Redis的SUBSCRIBE命令详解》Redis的SUBSCRIBE命令用于订阅一个或多个频道,以便接收发送到这些频道的消息,本文给大家介绍Redis的SUBSCRIBE命令,感兴趣的朋友跟随... 目录基本语法工作原理示例消息格式相关命令python 示例Redis 的 SUBSCRIBE 命令用于订

sky-take-out项目中Redis的使用示例详解

《sky-take-out项目中Redis的使用示例详解》SpringCache是Spring的缓存抽象层,通过注解简化缓存管理,支持Redis等提供者,适用于方法结果缓存、更新和删除操作,但无法实现... 目录Spring Cache主要特性核心注解1.@Cacheable2.@CachePut3.@Ca

Redis实现高效内存管理的示例代码

《Redis实现高效内存管理的示例代码》Redis内存管理是其核心功能之一,为了高效地利用内存,Redis采用了多种技术和策略,如优化的数据结构、内存分配策略、内存回收、数据压缩等,下面就来详细的介绍... 目录1. 内存分配策略jemalloc 的使用2. 数据压缩和编码ziplist示例代码3. 优化的

redis-sentinel基础概念及部署流程

《redis-sentinel基础概念及部署流程》RedisSentinel是Redis的高可用解决方案,通过监控主从节点、自动故障转移、通知机制及配置提供,实现集群故障恢复与服务持续可用,核心组件包... 目录一. 引言二. 核心功能三. 核心组件四. 故障转移流程五. 服务部署六. sentinel部署

基于Redis自动过期的流处理暂停机制

《基于Redis自动过期的流处理暂停机制》基于Redis自动过期的流处理暂停机制是一种高效、可靠且易于实现的解决方案,防止延时过大的数据影响实时处理自动恢复处理,以避免积压的数据影响实时性,下面就来详... 目录核心思路代码实现1. 初始化Redis连接和键前缀2. 接收数据时检查暂停状态3. 检测到延时过

Redis实现分布式锁全过程

《Redis实现分布式锁全过程》文章介绍Redis实现分布式锁的方法,包括使用SETNX和EXPIRE命令确保互斥性与防死锁,Redisson客户端提供的便捷接口,以及Redlock算法通过多节点共识... 目录Redis实现分布式锁1. 分布式锁的基本原理2. 使用 Redis 实现分布式锁2.1 获取锁

Redis中哨兵机制和集群的区别及说明

《Redis中哨兵机制和集群的区别及说明》Redis哨兵通过主从复制实现高可用,适用于中小规模数据;集群采用分布式分片,支持动态扩展,适合大规模数据,哨兵管理简单但扩展性弱,集群性能更强但架构复杂,根... 目录一、架构设计与节点角色1. 哨兵机制(Sentinel)2. 集群(Cluster)二、数据分片

redis数据结构之String详解

《redis数据结构之String详解》Redis以String为基础类型,因C字符串效率低、非二进制安全等问题,采用SDS动态字符串实现高效存储,通过RedisObject封装,支持多种编码方式(如... 目录一、为什么Redis选String作为基础类型?二、SDS底层数据结构三、RedisObject

Redis分布式锁中Redission底层实现方式

《Redis分布式锁中Redission底层实现方式》Redission基于Redis原子操作和Lua脚本实现分布式锁,通过SETNX命令、看门狗续期、可重入机制及异常处理,确保锁的可靠性和一致性,是... 目录Redis分布式锁中Redission底层实现一、Redission分布式锁的基本使用二、Red

redis和redission分布式锁原理及区别说明

《redis和redission分布式锁原理及区别说明》文章对比了synchronized、乐观锁、Redis分布式锁及Redission锁的原理与区别,指出在集群环境下synchronized失效,... 目录Redis和redission分布式锁原理及区别1、有的同伴想到了synchronized关键字