zoukankan      html  css  js  c++  java
  • 统一ID生成服务

    方案前提

    ID获取的大前提至少做到单表有序

    1、单机本地方案

    架构图

    原理:利用更新数据库字段方式实现 ID增长与持久化

    实现:

      1、建表t_id_provider, 包含字段 max_id(当前最大ID值) upd_time(最后一次更新时间)

      2、IdService获取id集合使用本地锁,先从数据库取出最大值cMaxId = max_id,然后根据 update max_id = (max_id+取Id个数) where max_id = cMaxId (进行max_id对比主要是防止代码加锁BUG导致重复ID,作为最后一道保障)

    优点:

      实现简单,代码量小

    缺点:

      不支持高并发, 且单机模式可用性低,一旦挂了其他服务就无法获取到ID

    2、集群本地方案

    架构图

    原理:工作原理和本地方案基本一致,区别是IdService获取ID集合由本地锁改为基于redis的分布式锁,集群服务用于保障高可用,以及提升不大的并发量(全局锁缘故)

    3、单机本地缓存方案

    架构图

    原理:本地缓存,取一次用多次的方式,服务重启后未使用的ID弃用

    实现:

      1、建表t_id_provider, 包含字段 max_id(当前最大ID值) upd_time(最后一次更新时间)

      2、IdService每次步长增加1万到10万不等,记录cId(当前ID) maxId(当前缓存最大可用ID)

      3、其他服务向IdService申请Id时对操作加锁,判断 cId+申请步长<=maxId,若小于等于则修改 cId=cId+申请步长,若不够则从数据库申请足够长度的步长(以万为单位),

      4、根据cId和步长大小,返回id集合

    缓存法是对单机方式的优化,极大减少与数据库交互,并发数显著上升,但因单机模式并发任然不算太高

    4、集群本地号段缓存方案

    架构图

    原理:号段预发本地缓存方式

    实现:

      1、建表t_id_provider, 包含字段 max_id(当前最大ID值) upd_time(最后一次更新时间)

      2、IdService每次步长增加1万到10万不等,记录cId(当前ID) maxId(当前缓存最大可用ID)

      3、IdService启动时向mysql申请号段(redis分布式锁加锁), 例:IdService1 cId=1 maxId=10000;IdService2 cId=10001 maxId=20000; IdService3 cId=20001 maxId=30000;

      4、其他服务向IdService申请Id时使用redis分布式锁进行加锁,判断 cId+申请步长<=maxId,若小于等于则修改 cId=cId+申请步长,若不够则从数据库申请足够长度的步长(以万为单位),

    关于拓展:若IdService服务需要横向拓展,增加号段提供

    故障转移:

    5、中间件REDIS方案(将运算交于REDIS)

    架构图

    原理:使用redis自带的 INCRBY计数命令,实现ID获取

    实现:

      1、基于redis单线程、高性能的特点,IdService部署集群模式用于保障可用性

      2、提前 设置redis硬盘持久化, 设置 key id_generator 永不过期,初始化id_generator 值

      3、使用redis自带的计数器功能INCRBY命令实现key的步长增长,并返回增长后的值 returnNum

      4、根据 returnNum和步长生成id集合并返回

    优点:

      基本满足高并发和高可用两点

    缺点:

      各个服务的id生成依赖于一个key, 集中于同一台REDIS服务器上

    改进

    对id_generator 进行拆分,生成多个key,每个key保存一个号段,使用完或者不够用则向id_generator申请,将取id的业务分散在多台redis服务器上

    例:hash("com.xxx.app.Test") = 100 再取余100%3=1,key为 id_generator_1,另有 id_generator_0和 id_generator_2,使用hash数据结构两个key分别是key_min key_max 作为区间使用

    通过以上计算方式我们可以将原本的 id_generator 分散到了不同的机器上,此时id_generator用以维护当前最大值 而相应的号段则分配在 id_generator_0、id_generator_1、id_generator_2

    当其他服务申请id集合时,通过计算得出key(id_generator_0、id_generator_1、id_generator_2),   执行lua脚本,脚本逻辑如下

    a、判断  申请ID个数 <= key_max-key_min+1 是否成立, 若成立 则key_min+=申请ID个数   返回key_min 

    b、若 申请ID个数 <= key_max-key_min+1 不成立,则 计算需要拓展值 num = 申请ID个数+1000 然后 对 id_generator INCRBY(num),key_max+=num, key_min+=申请ID个数  返回key_min

     

  • 相关阅读:
    Axure chrome 安装及已损坏的解决方法
    Ubuntu16.04上使用git
    ubuntu初探
    nginx入门笔记
    更改element-UI按钮默认样式
    js深拷贝与浅拷贝的区别及实现
    安装mysql-python的遇到的问题
    facebook atc弱网环境搭建和踩坑总结
    验证码识别 Tesseract的简单使用和总结
    selenium 基础(一)
  • 原文地址:https://www.cnblogs.com/xieyanke/p/13840727.html
Copyright © 2011-2022 走看看