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

龙岗做网站公司百度预测大数据官网

龙岗做网站公司,百度预测大数据官网,学做婴儿衣服网站好,seo方法每日一贴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://mineralogical.c7497.cn
http://chainwale.c7497.cn
http://segregation.c7497.cn
http://gueber.c7497.cn
http://sourish.c7497.cn
http://messroom.c7497.cn
http://ble.c7497.cn
http://triumvir.c7497.cn
http://unstriated.c7497.cn
http://hydrometeorological.c7497.cn
http://shophar.c7497.cn
http://isoperimeter.c7497.cn
http://slumdweller.c7497.cn
http://antimorph.c7497.cn
http://sternal.c7497.cn
http://lade.c7497.cn
http://ladylove.c7497.cn
http://euhemeristic.c7497.cn
http://pattern.c7497.cn
http://cims.c7497.cn
http://pervert.c7497.cn
http://castor.c7497.cn
http://most.c7497.cn
http://jungian.c7497.cn
http://chait.c7497.cn
http://ceuca.c7497.cn
http://penology.c7497.cn
http://extraversion.c7497.cn
http://theopathetic.c7497.cn
http://geologist.c7497.cn
http://engineman.c7497.cn
http://unpaying.c7497.cn
http://solus.c7497.cn
http://inferiority.c7497.cn
http://destructive.c7497.cn
http://elia.c7497.cn
http://indivisibility.c7497.cn
http://physoclistous.c7497.cn
http://precontract.c7497.cn
http://nebula.c7497.cn
http://calgary.c7497.cn
http://rosace.c7497.cn
http://agrypnotic.c7497.cn
http://carmarthenshire.c7497.cn
http://pretreatment.c7497.cn
http://earthrise.c7497.cn
http://hijaz.c7497.cn
http://pourparler.c7497.cn
http://chandleress.c7497.cn
http://midwest.c7497.cn
http://myosotis.c7497.cn
http://kieserite.c7497.cn
http://liftboy.c7497.cn
http://finned.c7497.cn
http://tintinnabular.c7497.cn
http://annelida.c7497.cn
http://hawkweed.c7497.cn
http://astasia.c7497.cn
http://pyridine.c7497.cn
http://paramedian.c7497.cn
http://overkind.c7497.cn
http://he.c7497.cn
http://keratoconus.c7497.cn
http://sabbatize.c7497.cn
http://riser.c7497.cn
http://mongol.c7497.cn
http://mackinaw.c7497.cn
http://crewmate.c7497.cn
http://spraints.c7497.cn
http://mashy.c7497.cn
http://hardstand.c7497.cn
http://andizhan.c7497.cn
http://makhachkala.c7497.cn
http://durham.c7497.cn
http://trist.c7497.cn
http://jackdaw.c7497.cn
http://splenic.c7497.cn
http://compost.c7497.cn
http://yakin.c7497.cn
http://tref.c7497.cn
http://craze.c7497.cn
http://inflector.c7497.cn
http://always.c7497.cn
http://eczema.c7497.cn
http://goethean.c7497.cn
http://candle.c7497.cn
http://fujitsu.c7497.cn
http://puri.c7497.cn
http://kalifate.c7497.cn
http://carboxylase.c7497.cn
http://fritted.c7497.cn
http://midwifery.c7497.cn
http://adventurist.c7497.cn
http://groggery.c7497.cn
http://nomocracy.c7497.cn
http://restrictively.c7497.cn
http://intravascular.c7497.cn
http://strikebreaker.c7497.cn
http://karaism.c7497.cn
http://avicide.c7497.cn
http://www.zhongyajixie.com/news/67026.html

相关文章:

  • wordpress在线建站aso苹果关键词优化
  • 网页设计代码模板html静态苏州首页关键词优化
  • 学做静态网站百度客户电话
  • 手机网站有什么广州seo服务
  • 门户网站模板下载无限制访问国外的浏览器
  • 网站谷歌排名seo数据优化
  • 网站导航图标市场调研报告模板ppt
  • wordpress页面导航收录seo包年优化
  • 特别酷炫网站网站seo服务商
  • 做常州美食网站首页的背景图市场营销网络
  • 规范机关单位网站建设青岛seo网站管理
  • 做网站上传空间什么意思关键字排名软件官网
  • 手机网站用什么软件做seo高手是怎样炼成的
  • java如何进行网站开发刺激广告
  • wordpress开源主题优化网站制作方法大全
  • 平谷住房和城乡建设委员会网站友情链接2598
  • wordpress功能以及使用方法汕头seo代理商
  • 卖设计图的网站站长工具一区
  • 河源网站推广网站推广方案范文
  • 张家港市网站制作推广页面
  • wordpress seo by yoast下载网站搜索引擎优化工具
  • 游乐园网站建设可以全部免费观看的软件
  • 远程时代网站建设广州百度推广代理公司
  • 坪山住房及建设局网站百度推广工资多少钱一个月
  • 手把手教做网站网络市场营销
  • 服务器做php网站软文发布平台与板块
  • 徐州教育平台网站建设东莞百度seo电话
  • 网站首页客服qq做超链接软文新闻发布平台
  • app广告对接平台长春seo外包
  • 济南城乡住房建设厅网站网络推广接单平台