当前位置: 首页 > news >正文

免费网站制作 优帮云域名是什么

免费网站制作 优帮云,域名是什么,外包网站建设,椒江区建设局网站hello。大家好,我是灰小猿,一个超会写bug的程序猿! 在分布式项目中,数据表的主键ID一般可能存在于UUID或自增ID这两种形式,UUID好理解而且实现起来也最容易,但是缺点就是数据表中的主键ID是32位的字符串&a…

hello。大家好,我是灰小猿,一个超会写bug的程序猿!

在分布式项目中,数据表的主键ID一般可能存在于UUID或自增ID这两种形式,UUID好理解而且实现起来也最容易,但是缺点就是数据表中的主键ID是32位的字符串,在大数据查询等情况下性能会相对比较差,所以在需求允许的情况下,我们通常会优先考虑使用自增ID来代替UUID使用。

在分布式项目中如果你的数据表的主键ID是自增ID,那么常见的生成对象主键ID的方式有:

  • 雪花算法

    • 优点:实现简单

    • 缺点:生成ID较长、生成ID不连续,会造成ID浪费

  • 采用框架自带的ID生成器,如MybatisPlus的@AutoID

    • 优点:依赖框架,实现简单

    • 缺点:无法在插入对象前获取到对象的主键ID

  • 采用Redis缓存生成主键ID等

    • 优点:生成的ID连续,数据在表中的可读性好

    • 缺点:借助Redis缓存,实现相比前两种较复杂

通过雪花算法生成对象主键ID的方式我们在之前的文章中已经介绍过了,这篇文章我们主要介绍如何通过Redis来实现生成对象自增ID的方法。

1、缓存实现原理

通过Redis实现对象自增ID的方式,主要是通过Redis的INCRINCRBY 命令来对键值进行递增操作,从而实现计数器的功能,主要原因是Redis 是单线程模型,所有命令都是原子操作,不会发生竞态条件,

在使用时要留意以下特点与注意事项

  1. 原子性INCRINCRBYINCRBYFLOAT 命令都是原子性的,这意味着如果多个客户端同时执行这些命令,Redis 会保证每个命令的执行不会发生竞态条件。

  2. 数据类型要求:这些命令要求操作的值是整数(INCRINCRBY)或浮点数(INCRBYFLOAT)。如果键对应的值不是数值类型,Redis 会返回错误。

  3. 性能:Redis 是单线程的,所有命令都是原子操作,因此在高并发环境下执行这些命令时,性能表现非常好。

  4. 键不存在的情况:如果执行 INCRINCRBY 时,键不存在,Redis 会自动创建这个键并初始化其值为 0,然后进行递增。

2、Redis工具类实现ID自动生成

了解到通过Redis实现的原理之后,就是如何设计缓存以保证每张表的数据之间不会相互影响,

以user表为例,对应的model为UserModel,那么我们就可以将model名称作为key,当前已有的最大的ID作为value来进行存储,因为每一张表对应的model名称都是不一样的,所以这里一定不会出现key重复的情况,

下面是一些在Redis中生成和获取对象自增ID的工具方法,方便新建对象时直接调用

@Component("redisUtils")
@RequiredArgsConstructor
@Slf4j
public class RedisUtils implements InitializingBean {private final StringRedisTemplate stringRedisTemplate;private static RedisUtils redisUtils;@Overridepublic void afterPropertiesSet() {redisUtils = this;}/*** 获取自增ID*/public static <T> Integer getIncr(Class<T> tClass) {try {String key = tClass.getName();Long increment = redisUtils.stringRedisTemplate.opsForValue().increment(key, 1);return Math.toIntExact(increment);} catch (Exception e) {e.printStackTrace();throw new RedisSystemException(e.getMessage(), e);}}/*** 获取自增ID,指定递增长度,用于批量创建对象时,只请求一次Redis* 如批量创建五个对象,delta等于5*/public static <T> Integer getIncr(Class<T> tClass, int delta) {try {String key = tClass.getName();Long increment = redisUtils.stringRedisTemplate.opsForValue().increment(key, delta);return Math.toIntExact(increment);} catch (Exception e) {e.printStackTrace();throw new RedisSystemException(e.getMessage(), e);}}/*** 缓存预热,用于项目启动时初始化Redis中各个表的最大ID*/public static <T> long incrPreheat(Class<T> tClass, Long maxValue) {if (maxValue == null) {maxValue = 0L;}if (maxValue < 0) {//异常抛出,预热的初始值不能小于0}Integer incr = getIncr(tClass);if (maxValue <= incr) {return incr;}return getIncr(tClass, (int) (maxValue - incr));}
}

解释:InitializingBean是Spring提供的拓展性接口,InitializingBean接口为bean提供了属性初始化后的处理方法,它只有一个afterPropertiesSet方法,凡是继承该接口的类,在bean的属性初始化后都会执行该方法。

3、缓存预热

缓存预热是指在项目启动时,将每一张表当前最大的主键ID预先加载到Redis中,这样在后面使用的时候,就可以直接从Redis中获取下一次ID即可,不需要再去访问数据库查询最大ID,缓存预热一般会建立在Redis专门的初始化类中,以便在启动项目时可以运行该类,具体如下:

/*** 缓存预热** @author hxy*/
@Component
@DependsOn("redisUtils")
@RequiredArgsConstructor
public class RedisInit {private final UserMapper userMapper;/*** 获取每一张表中当前的最大ID,然后预热到redis中*/@PostConstructpublic void init() {RedisUtils.incrPreheat(UserModel.class, userMapper.maxId());}
}

解释:@DependsOn注解可以定义在类和方法上,意思是我这个组件要依赖于另一个组件,也就是说被依赖的组件会比该组件先注册到IOC容器中。

解释:@PostConstruct注解

在Java中,@PostConstruct注解,通常用于标记一个方法,它表示该方法在类实例化之后(通过构造函数创建对象之后)立即执行。

加上@PostConstruct注解的方法会在对象的所有依赖项都已经注入完成之后执行。通过使用@PostConstruct注解,我们可以确保在对象完全创建和初始化之后才执行这些操作。这个注解通常用在依赖注入(Dependency Injection)的框架中,例如Spring。

@PostConstruct 注解可以用在任何类的方法上,但它最常用于标记在 Spring Framework 中的 Bean 类中的初始化方法。

4、model层封装调用

在实例化一个model对象的时候,要将model的主键ID进行赋值,这个时候就要从Redis中获取到当前对象应该对应的主键ID,我们可以在model类中构建一个newInstance方法或有参构造,来专门的生成需要赋值主键ID的对象,在方法中调用redis工具类的getIncr方法,获取到最新最小未使用的主键ID并赋值给新建的model即可。

@Getter
@Setter
public class UserModel {private Integer id;private String name;private Integer age;private String tel;public UserModel() {}/*** 提供一个能够生成自增ID的有参构造,需要生成自增ID时调用*/public UserModel(boolean autoId) {if (autoId) {this.id = RedisUtils.getIncr(UserModel.class);}}
}

如果你是需要批量创建对象并且给对象赋值主键ID的情况,可以按照如下方式使用,这样可以只调用一次Redis,避免重复调用Redis影响性能。

@Service
@RequiredArgsConstructor
public class UserServiceImpl {private final UserMapper userMapper;public void batchAddUser(){int addNumber = 10;//提前生成自定跨度的ID,比如之前最大ID是6,获取后得到的incr是16Integer incr = RedisUtils.getIncr(UserModel.class, addNumber);List<UserModel> userModels = new ArrayList<>();for (int i = 0; i < addNumber; i++) {UserModel userModel = new UserModel();//每一个主键ID依次递减使用userModel.setId(incr--);userModels.add(userModel);}userMapper.insertBatch(userModels);}
}

至此,通过Redis来获取对象自增ID的方法已经完成,如果在使用过程中有其他场景需求,可以对redisUtils中的方法进行拓展即可。

我是灰小猿,我们下期见!

http://www.khdw.cn/news/5345.html

相关文章:

  • 素材网站陕西seo公司
  • 简单的网站开发免费的seo网站下载
  • php做动态网站如何修改密码线上营销方案
  • 企业网站开发工具沈阳网络优化培训
  • 网站的侧边栏怎么做今日国内新闻热点
  • 网站推广网站制作网站建设公司关键词搜索工具好站网
  • 云虚拟主机怎么做2个网站产品推广方案怎么写
  • 建设企业网站的具体步骤外贸网络营销平台
  • 深圳营销型网站建设服务商域名注册 阿里云
  • 简单网站建设论文总结软文网站
  • 微信客户端网站建设关键词搜索引擎工具爱站
  • wordpress做查询系统百度地图排名怎么优化
  • 金华专业做网站我想在百度上做广告怎么做
  • 长基建站泉州百度首页优化
  • 头条号可以做网站链接吗推广代理平台
  • php网站留言板模板下载浏览器网站进入口
  • 南昌智能建站模板重庆seo关键词排名
  • 南山网站制作私人浏览器
  • 秦皇岛网站关键词推广海外推广渠道
  • 做网站 不做源码网上营销培训课程
  • 平谷武汉阳网站建设500个游戏推广群
  • 自己的电脑可以做网站服务器最近疫情最新消息
  • 网站logo怎么做的网络营销的四大基础理论
  • 织梦做的网站织梦修改网页百度排名
  • 苏州艺术家网站建设一站式营销平台
  • 泾县网站建设百度竞价sem
  • 做婚纱摄影网站多少钱杭州seo外包服务
  • 成都 做网站 模版优化seo公司哪家好
  • 做网站点子开发一个app需要多少钱
  • 网站单页在线制作免费网站代理访问