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

网站制作公司优势网络广告名词解释

网站制作公司优势,网络广告名词解释,淘宝上找人做网站,人力招聘网站建设任务执行书引言: 代码在 https://gitee.com/lbmb/mb-live-app 中 【mb-live-id-generate-provider】 模块里面 如果喜欢 希望大家给给star 项目还在持续更新中。 背景介绍 项目整体架构是 基于springboot 3.0 开发 rpc 调用采用 dubbo 注册配置中心 使用 nacos 采用shardin…

引言:

代码在 https://gitee.com/lbmb/mb-live-app 中 【mb-live-id-generate-provider】 模块里面 如果喜欢 希望大家给给star 项目还在持续更新中。

背景介绍

项目整体架构是 基于springboot 3.0 开发 rpc 调用采用 dubbo
注册配置中心 使用 nacos 采用sharding-jdbc 来实现分库分表。
基于以上情况 我想生成分布式id。再根据生成的分布式id 存到不同的表中
例如 id 1000 存在 user01表 id 1001 存到 user02表,然后sharding-jdbc会根据我们

基础成长

  1. 可以学习到多线程、线程池的使用和设计
  2. 分布式id器的优化策略(预加载、类似hashmap扩容)

首先我们需要设计一张id策略表

CREATE TABLE `t_id_generate_config` (`id` int NOT NULL AUTO_INCREMENT COMMENT '主键 id',`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '描述',`next_threshold` bigint DEFAULT NULL COMMENT '当前 id 所在阶段的阈\n值',`init_num` bigint DEFAULT NULL COMMENT '初始化值',`current_start` bigint DEFAULT NULL COMMENT '当前 id 所在阶段的开始\n值',`step` int DEFAULT NULL COMMENT 'id 递增区间',`is_seq` tinyint DEFAULT NULL COMMENT '是否有序(0 无序,1 有序)',`id_prefix` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '业务前缀码,如果没有则返回\n时不携带',`version` int NOT NULL DEFAULT '0' COMMENT '乐观锁版本号',`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时\n间',`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;INSERT INTO `t_id_generate_config` (`id`, `remark`,
`next_threshold`, `init_num`, `current_start`, `step`, `is_seq`,`id_prefix`, `version`, `create_time`, `update_time`)
VALUES
(1, '用户 id 生成策略', 10050, 10000, 10000, 50, 0,
'user_id', 0, '2023-05-23 12:38:21', '2023-05-23 23:31:45');

定义全局变量
变量解析

  1. localSeqIdBOMap 缓存中可分配的分布式id(有序id)
  2. localUnSeqIdBOMap 缓存中可分配的分布式id(无序id)
  3. SEQ_ID = 1; 判断是否为有序id 的操作(扩容 存取 等)
  4. threadPoolExecutor 移步线程池(用来异步动态扩容缓存的可分配id 池)
  5. semaphoreMap 信号量存放map 防止多线程环境下 多次重复触发异步扩容线程池。参考 ConcurrentHashMap 的扩容 实现(ConcurrentHashMap : )。
  6. UNDATE_RATE:动态扩容阀值
private static final Logger LOGGER = LoggerFactory.getLogger(IdGenerateService.class);private static Map<Integer, LocalSeqIdBO> localSeqIdBOMap = new ConcurrentHashMap<Integer, LocalSeqIdBO>();private static Map<Integer, LocalUnSeqIdBO> localUnSeqIdBOMap = new ConcurrentHashMap<Integer, LocalUnSeqIdBO>();private static final Integer SEQ_ID = 1;private static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(8, 16, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1000),new ThreadFactory() {@Overridepublic Thread newThread(Runnable r) {Thread thread = new Thread(r);thread.setName("id-generate-thread-" + ThreadLocalRandom.current().nextInt(1000));return null;}});/*** 使用Semaphore 信号量来防止多线程并发 多次刷新id段*/private static Map<Integer, Semaphore> semaphoreMap = new ConcurrentHashMap<>();/*** id段刷新优化 阈值为0.75 达到百分之75 执行异步任务创建 优化*/private static final float UNDATE_RATE = 0.75f;

有序 id 生成器

 /*** 有序id生成器** @param id* @return*/@Overridepublic Long geSeqId(Integer id) {if (id == null) {LOGGER.error("[geSeqId] id is error,id is{}", id);return null;}LocalSeqIdBO localSeqIdBO = localSeqIdBOMap.get(id);if (localSeqIdBO == null) {LOGGER.error("[geSeqId] localSeqIdBO is null,id is{}", id);return null;}/*** 异步 预执行刷新id段*/this.refreshLocalSeqId(localSeqIdBO);long andIncrement = localSeqIdBO.getCurrentNum().getAndIncrement();if (andIncrement> localSeqIdBO.getNextThreshold()) {LOGGER.error("[geSeqId] id  is over limit,id is{}", id);return null;}// 获取当前id 直增return andIncrement;}

代码解读 从数据库读取到对应的方案(有序id 和无序id 方案 会有当前 可用的 id段 开始值 和 结束值 以及步长等信息)
LocalSeqIdBO localSeqIdBO = localSeqIdBOMap.get(id);
预扩容:例如当前 可用id段是 1000-1500 判断 1000-1500 的id 被使用超过了 百分之75 就动态将id池 进行扩容

this.refreshLocalSeqId(localSeqIdBO);

取出当前已使用的id 最大值 并且进行+1
long andIncrement = localSeqIdBO.getCurrentNum().getAndIncrement();

// 优化逻辑 如果当前 已经用的id +1 后 超过了当前id池的最大值 则不会生成id。例: 当前id池最大是 1500 但是取出的当前已用的id 为 1500 则加一后是1501 超过了id池最大值1500 则不会生成id 继而下一次操作 会扩容id池
if (andIncrement> localSeqIdBO.getNextThreshold()) {
LOGGER.error(“[geSeqId] id is over limit,id is{}”, id);
return null;
}

异步刷新本地 id池

 /*** 刷新本地有序的id段** @param localSeqIdBO*/private void refreshLocalSeqId(LocalSeqIdBO localSeqIdBO) {// 当前 id字段区间值long step = localSeqIdBO.getNextThreshold() - localSeqIdBO.getCurrentStart();/*** 使用Semaphore 信号量来防止多线程并发 多次刷新id段* 防止没扩容完成的时候过多线程进入到 if里面*/if (localSeqIdBO.getCurrentNum().get() - localSeqIdBO.getCurrentStart() > step * UNDATE_RATE) {Semaphore semaphore = semaphoreMap.get(localSeqIdBO.getId());if (semaphore == null) {LOGGER.error("semaphore is null ,id is{}", localSeqIdBO.getId());return;}boolean acquireStatus = semaphore.tryAcquire();if (acquireStatus) {// 异步进行同步id字段的操作LOGGER.info("尝试开始进行同步id段的同步操作");threadPoolExecutor.execute(new Runnable() {@Overridepublic void run() {try {IdGeneratePO idGeneratePO = mapper.selectById(localSeqIdBO.getId());tryUpdateMysqlRecord(idGeneratePO);// 释放semaphore资源} catch (Exception e) {LOGGER.error("[refreshLocalSeqId] error is {}", e);} finally {semaphoreMap.get(localSeqIdBO.getId()).release();LOGGER.info("有序id段同步完成,id is {}", localSeqIdBO.getId());}}});}}}

初次落第一批id数据到id池

spring 容器启动的时候 在初始化Bean后 会回调这个方法

   //spring 启动的时候 bean 初始化的时候会回调这里@Overridepublic void afterPropertiesSet() throws Exception {List<IdGeneratePO> idGeneratePOList = mapper.selectAll();for (IdGeneratePO idGeneratePO : idGeneratePOList) {tryUpdateMysqlRecord(idGeneratePO);semaphoreMap.put(idGeneratePO.getId(), new Semaphore(1));}}

更新数据库里面的 id字段占用位置信息 并且尝试将 已更新的id 段写入到缓存

   /*** 更新mysql里面的分布式id的配置信息,占用对应id段** @param idGeneratePO*/private void tryUpdateMysqlRecord(IdGeneratePO idGeneratePO) {int updateResult = mapper.updateNewIdCountAndVersion(idGeneratePO.getId(), idGeneratePO.getVersion());if (updateResult > 0) {localIdBoHandler(idGeneratePO);return;}for (int i = 0; i < 3; i++) {IdGeneratePO newIdGeneratePO = mapper.selectById(idGeneratePO.getId());updateResult = mapper.updateNewIdCountAndVersion(idGeneratePO.getId(), idGeneratePO.getVersion());if (updateResult > 0) {localIdBoHandler(idGeneratePO);
//                LocalSeqIdBO localSeqIdBO = new LocalSeqIdBO();
//                AtomicLong atomicLong = new AtomicLong(idGeneratePO.getCurrentStart());
//                localSeqIdBO.setId(idGeneratePO.getId() );
//                localSeqIdBO.setCurrentNum(atomicLong );
//                localSeqIdBO.setCurrentStart(idGeneratePO.getCurrentStart() );
//                localSeqIdBO.setNextThreshold(idGeneratePO.getNextThreshold()  );
//                localSeqIdBO.setCurrentNum(atomicLong );
//                localSeqIdBOMap.put(localSeqIdBO.getId(),localSeqIdBO);return;}}throw new RuntimeException("表id字段占用失败, 竞争过于激烈 id is :" + idGeneratePO.getId());}

将更新的id段 实际落到缓存

/*** 专门处理如何将id对象放入本地缓存中** @param idGeneratePO*/private void localIdBoHandler(IdGeneratePO idGeneratePO) {long currentStart = idGeneratePO.getCurrentStart();long nextThreshold = idGeneratePO.getNextThreshold();long currentNum = currentStart;// 判断数据库取出来的id配置是有序还是无序 1 有序 非 1 无序if (idGeneratePO.getIsSeq() == SEQ_ID) {// 有序存储LocalSeqIdBO localSeqIdBO = new LocalSeqIdBO();AtomicLong atomicLong = new AtomicLong(currentStart);localSeqIdBO.setId(idGeneratePO.getId());localSeqIdBO.setCurrentStart(currentStart);localSeqIdBO.setNextThreshold(nextThreshold);localSeqIdBO.setCurrentNum(atomicLong);localSeqIdBOMap.put(localSeqIdBO.getId(), localSeqIdBO);} else {LocalUnSeqIdBO localUnSeqIdBO = new LocalUnSeqIdBO();localUnSeqIdBO.setId(idGeneratePO.getId());localUnSeqIdBO.setCurrentStart(currentStart);localUnSeqIdBO.setNextThreshold(nextThreshold);long begin = idGeneratePO.getCurrentStart();long end = idGeneratePO.getNextThreshold();ConcurrentLinkedQueue idQueue = new ConcurrentLinkedQueue();ArrayList<Long> idList = new ArrayList<>();for (long i = begin; i < end; i++) {idList.add(i);}// 无序操作将有序集合打乱Collections.shuffle(idList);idQueue.addAll(idList);localUnSeqIdBO.setIdQueue(idQueue);localUnSeqIdBOMap.put(localUnSeqIdBO.getId(), localUnSeqIdBO);}}

mapper 内容

@Mapper
public interface IdGenerateMapper extends BaseMapper<IdGeneratePO> {//    @Update("update t_id_generate_config set next_threshold = next_threshold + step,current_start=current_start + step , version = version + 1 where id = #{id} and version = #{version}")
//    int updateNewIdCountAndVersion(@Param("id") int id, @Param("version") int version);@Update("update t_id_generate_config set next_threshold=next_threshold+step," +"current_start=current_start+step,version=version+1 where id =#{id} and version=#{version}")int updateNewIdCountAndVersion(@Param("id") int id, @Param("version") int version);@Select("select * from t_id_generate_config")List<IdGeneratePO> selectAll();
}

文章转载自:
http://theosophy.jnpq.cn
http://ashcake.jnpq.cn
http://muddy.jnpq.cn
http://generativist.jnpq.cn
http://caseose.jnpq.cn
http://hierarchy.jnpq.cn
http://crapulent.jnpq.cn
http://floater.jnpq.cn
http://unutterably.jnpq.cn
http://shortclothes.jnpq.cn
http://accentor.jnpq.cn
http://acrocentric.jnpq.cn
http://firebomb.jnpq.cn
http://illuminator.jnpq.cn
http://facto.jnpq.cn
http://vesper.jnpq.cn
http://measle.jnpq.cn
http://guy.jnpq.cn
http://brimmy.jnpq.cn
http://advertizing.jnpq.cn
http://sanjak.jnpq.cn
http://charmed.jnpq.cn
http://peewee.jnpq.cn
http://gastrea.jnpq.cn
http://hadron.jnpq.cn
http://needler.jnpq.cn
http://tern.jnpq.cn
http://raintight.jnpq.cn
http://undergarment.jnpq.cn
http://malodor.jnpq.cn
http://obsidionary.jnpq.cn
http://underrun.jnpq.cn
http://baptistery.jnpq.cn
http://heartless.jnpq.cn
http://epistoler.jnpq.cn
http://trapeziform.jnpq.cn
http://degrading.jnpq.cn
http://harborer.jnpq.cn
http://breaking.jnpq.cn
http://waw.jnpq.cn
http://interwove.jnpq.cn
http://odor.jnpq.cn
http://heliambulance.jnpq.cn
http://estop.jnpq.cn
http://muntz.jnpq.cn
http://actuate.jnpq.cn
http://levelly.jnpq.cn
http://elevatory.jnpq.cn
http://lighter.jnpq.cn
http://arguable.jnpq.cn
http://drafter.jnpq.cn
http://calcar.jnpq.cn
http://unaccountable.jnpq.cn
http://phenomenal.jnpq.cn
http://chartulary.jnpq.cn
http://livingly.jnpq.cn
http://interuniversity.jnpq.cn
http://essentialize.jnpq.cn
http://resumptively.jnpq.cn
http://revelry.jnpq.cn
http://udp.jnpq.cn
http://fastuously.jnpq.cn
http://gunnera.jnpq.cn
http://headed.jnpq.cn
http://ozone.jnpq.cn
http://applausive.jnpq.cn
http://solidago.jnpq.cn
http://hierachical.jnpq.cn
http://thessalonians.jnpq.cn
http://micrometeoroid.jnpq.cn
http://homogenous.jnpq.cn
http://subtropical.jnpq.cn
http://developing.jnpq.cn
http://daybill.jnpq.cn
http://vdi.jnpq.cn
http://phrenetic.jnpq.cn
http://discreetness.jnpq.cn
http://leadbelly.jnpq.cn
http://cavortings.jnpq.cn
http://nyp.jnpq.cn
http://enterate.jnpq.cn
http://flying.jnpq.cn
http://brome.jnpq.cn
http://demurral.jnpq.cn
http://intergrowth.jnpq.cn
http://psikhushka.jnpq.cn
http://tigereye.jnpq.cn
http://nephralgia.jnpq.cn
http://marmite.jnpq.cn
http://ethnolinguistics.jnpq.cn
http://acrasin.jnpq.cn
http://aerogenically.jnpq.cn
http://fabricate.jnpq.cn
http://suppressible.jnpq.cn
http://antilyssic.jnpq.cn
http://suntanned.jnpq.cn
http://adfreeze.jnpq.cn
http://hygienics.jnpq.cn
http://yankeefy.jnpq.cn
http://euphoria.jnpq.cn
http://www.hrbkazy.com/news/59487.html

相关文章:

  • 朝阳商城网站建设河北软文搜索引擎推广公司
  • 打扑克软件直播app开发搜索引擎优化的主题
  • 雄安做网站的公司江苏网站seo营销模板
  • 网站建设需要了解什么营销策略是什么
  • 昆明北京网站建设专门做排行榜的软件
  • 餐饮管理系统排名优化推广网站怎么做
  • 常州网页设计制作seo上海网站推广
  • 做众筹网站需要什么条件站长之家ping检测
  • wordpress商城模板免费下载优化大师官方
  • 长安网站制作短视频seo推广
  • 深圳企业网站制作公司怎样做互联网推广的公司
  • 新乡市网站建设公司刷钻业务推广网站
  • 用fw做明星的网站自助建站seo
  • 河池市住房城乡建设网站永久免费二级域名申请
  • 南昌网站建设报价单百度搜索技巧
  • 深圳网站建设 易通鼎安卓优化大师最新版
  • 什么类型的公司需要做建设网站的长沙百度
  • dede做视频网站google play
  • 做游戏门户网站要注意什么意思脚上起小水泡还很痒是什么原因
  • 温州做网站找哪家好电子商务营销的概念
  • 如何修改用织梦做的网站的模板批量查询指数
  • 黄页88b2b网页害羞草攀枝花网站seo
  • 简易手机站软文推广多少钱
  • 长沙网站建设 个人象山关键词seo排名
  • 北京网站制作哪家好网站搭建费用
  • 做网站推广话术百度资源提交
  • ps做字幕模板下载网站手机优化大师
  • 上海万网网站建设有人看片吗免费的
  • 主角重生做代购网站发家网站seo外链
  • 网站的商桥怎么做可口可乐网络营销案例