范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

可以来了解了解UUID的弊端以及雪花算法

  一、问题为什么需要分布式全局唯一ID以及分布式ID的业务需求
  在复杂分布式系统中,往往需要对大量的数据和消息进行唯一标识 如在美团点评的金融、支付、餐饮、酒店; 猫眼电影等产品的系统中数据日渐增长,对数据分库分表后需要有一个唯一ID来标识一条数据或消息; 特别一点的如订单、骑手、优惠券也都需要有唯一ID做标识。
  此时一个能够生成全局唯一ID的系统是非常必要的 ID生成规则部分硬性要求①全局唯一
  即不能出现重复ID号 ②趋势递增
  在Mysql的InnoDB引擎中使用的是聚集索引,由于多数RDBMS使用的是BTree的数据结构作为存储索引数据,在主键的选择上我们应该尽量使用有序的主键保证写入性能 ③单调递增
  保证下一个ID一定大于上一个ID,如事务版本号、排序等特殊要求 ④信息安全
  如果ID是连续的,恶意用户的扒取工作就非常容易做了,直接按照顺序下载指定URL即可:如果是订单号就更危险了,竞对可以直接知道我们一天的单量。所以在一些应用场景下,需要ID无规则不规则,让竞争对手不好猜 ⑤含时间戳
  在开发中能快速了解这个分布式id生成的时间 ID号生成系统的可用性要求①高可用
  发一个获取分布式ID的请求,服务器要保证99.999%的情况下能给我返回一个分布式ID ②低延迟
  返回的速度要快 ③高QPS(抵抗高访问)
  比如一秒内10万个,需要服务器能抵抗住并且生成10万个分布式ID 二、一般通用方案(一)UUID
  jdk自带,生成36位字符,形式为8-4-4-4-12,包含4个连号-,对于单体式仅需满足唯一的话可以使用 好处:性能高,本地生成,无网络消耗 坏处:无序且字符串长,存入数据库会增大数据库压力,入数据库性能差。mysql官方推荐主键越短越好
  索引, B+树索引的分裂
  既然分布式id是主键,然后主键是包含索引的,然后mysql的索引是通过b+树来实现的,每一次新的UUID数据的插入,为了查询的优化,都会对索引底层的b+树进行修改,因为UUID数据是无序的。
  所以 每一次UUID数据的插入都会对主键地的b+树进行很大的修改,这一点很不好。 插入完全无序,不但会导致一些中间节点产生分裂,也会白白创造出很多不饱和的节点,这样大大降低了数据库插入的性能 (二)数据库自增主键
  数据库自增主键实现原理:数据库自增id和 replace into 实现的
  REPLACE INTO 的含义是插入一条记录,如果表中唯一索引的值遇到冲突,则替换老数据
  那数据库自增ID机制适合作分布式ID吗? 答案是不太适合 系统水平扩展比较困难,比如定义好了步长和机器台数之后,如果要添加机器该怎么做? 假设现在只有一台机器发号是1,2.3.4.5(步长是1),这个时候需要扩容机器一台。可以这样做,把第二台机器的初始值设置得比第一台超过很多,貌似还好,现在想象一下如果我们线上有100台机器,这个时候要扩容该怎么做? 简直是噩梦。所以系统水平扩展方案复杂难以实现。 数据库压力还是很大,每次获取ID都得读写一次数据库,非常影响性能,不符合分布式ID里面的延迟低和要高QPS的规则(在高并发下,如果都去数据库里面获取id,那是非常影响性能的) (三)Redis生成全局id策略
  因为Redis是单线的天生保证原子性,可以使用原子操作INCR和INCRBY来实现
  注意:在Redis集群情况下,同样和MySQL一样需要设置不同的增长步长,同时key一定要设置有效期
  可以使用Redis集群来获取更高的吞吐量。
  假如一个集群中有5台Redis。可以初始化每台Redis的值分别是1,2,3,4,5,然后步长都是5。
  各个Redis生成的ID为: A: 1,6,11,16,21 B: 2,7,12,17,22 C: 3,8,13,18,23 D: 4,9,14,19,24 E: 5,10,15,20,25 三、snowflake(一)概述
  官网:
  https://github.com/twitter-archive/snowflake
  Twitter的分布式自增ID算法
  特点:
  ① 能够按照时间有序生成
  ②Snowflake算法生成id的结果是一个64bit大小的整数,为一个Long型,转化为字符串最多19位
  ③分布式系统内不会产生ID碰撞(由datacenter和workerld作区分) 并且效率较高。 (二)结构
  bit表示 -,id一般为正,所以固定为0
  时间戳位范围为 0-2^41 次方,大概是可以使用69年(从1970算起)
  工作进程位最多为 2^10 ,即1024个节点,包括5位datacenter和5位workerld作区分
  12bit-序列号,序列号,用来记录同毫秒内产生的不同id。12位(bit) 可以表示的最大正整数是 2^12-1=4059 (三)代码/**  * Twitter_Snowflake
  * SnowFlake的结构如下(每部分用-分开):
  * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000
  * 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0
  * 41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截)  * 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。41位的时间截,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69
  * 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId
  * 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号
  * 加起来刚好64位,为一个Long型。
  * SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID左右。  */ public class SnowflakeIdWorker {     // ==============================Fields===========================================     /** 开始时间截 (2020-08-28) */     private final long twepoch = 1598598185157L;       /** 机器id所占的位数 */     private final long workerIdBits = 5L;       /** 数据标识id所占的位数 */     private final long datacenterIdBits = 5L;       /** 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */     private final long maxWorkerId = -1L ^ (-1L << workerIdBits);       /** 支持的最大数据标识id,结果是31 */     private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);       /** 序列在id中占的位数 */     private final long sequenceBits = 12L;       /** 机器ID向左移12位 */     private final long workerIdShift = sequenceBits;       /** 数据标识id向左移17位(12+5) */     private final long datacenterIdShift = sequenceBits + workerIdBits;       /** 时间截向左移22位(5+5+12) */     private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;       /** 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) */     private final long sequenceMask = -1L ^ (-1L << sequenceBits);       /** 工作机器ID(0~31) */     private long workerId;       /** 数据中心ID(0~31) */     private long datacenterId;       /** 毫秒内序列(0~4095) */     private long sequence = 0L;       /** 上次生成ID的时间截 */     private long lastTimestamp = -1L;       //==============================Constructors=====================================     /**      * 构造函数      * @param workerId 工作ID (0~31)      * @param datacenterId 数据中心ID (0~31) 此方法是判断传入的机房号和机器号是否超过了最大值,即31,或者小于0      */     public SnowflakeIdWorker(long workerId, long datacenterId) {         if (workerId > maxWorkerId || workerId < 0) {             throw new IllegalArgumentException(String.format("worker Id can"t be greater than %d or less than 0", maxWorkerId));         }         if (datacenterId > maxDatacenterId || datacenterId < 0) {             throw new IllegalArgumentException(String.format("datacenter Id can"t be greater than %d or less than 0", maxDatacenterId));         }         this.workerId = workerId;         this.datacenterId = datacenterId;     }       // ==============================Methods==========================================     /*      * 核心方法      * 获得下一个ID (该方法是线程安全的)      * @return SnowflakeId      */     public synchronized long nextId() {         //1.获取当前的系统时间         long timestamp = timeGen();           //如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常         if (timestamp < lastTimestamp) {             throw new RuntimeException(                     String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));         }           //如果是同一时间生成的,则进行毫秒内序列         if (lastTimestamp == timestamp) {             // sequence 要增1, 但要预防sequence超过 最大值4095,所以要 与 SEQUENCE_MASK 按位求与              // 即如果此时sequence等于4095,加1后为4096,再和4095按位与后,结果为0             sequence = (sequence + 1) & sequenceMask;             // 毫秒内序列溢出             if (sequence == 0) {                 //阻塞到下一个毫秒,获得新的时间戳                 timestamp = tilNextMillis(lastTimestamp);             }         }         //时间戳改变,毫秒内序列重置         else {             sequence = 0L;         }           //上次生成ID的时间截         //把当前时间赋值给 lastTime, 以便下一次判断是否处在同一个毫秒内         lastTimestamp = timestamp;           //移位并通过或运算拼到一起组成64位的ID          long id = ((timestamp - twepoch) << timestampLeftShift) // 时间戳减去默认时间 再左移22位 与运算                 | (datacenterId << datacenterIdShift) // 机房号 左移17位 与运算                 | (workerId << workerIdShift) // 机器号 左移12位 与运算                 | sequence; // 序列号无需左移 直接进行与运算         return id;     }       /**      * 阻塞到下一个毫秒,直到获得新的时间戳      * @param lastTimestamp 上次生成ID的时间截      * @return 当前时间戳      */     protected long tilNextMillis(long lastTimestamp) {         long timestamp = timeGen();         while (timestamp <= lastTimestamp) {             timestamp = timeGen();         }         return timestamp;     }       /**      * 返回以毫秒为单位的当前时间      * @return 当前时间(毫秒)      */     protected long timeGen() {         return System.currentTimeMillis();     }       //==============================Test=============================================     /** 测试 */     public static void main(String[] args) {         SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 0);         for (int i = 0; i < 1000; i++) {             long id = idWorker.nextId();             System.out.println(id);         }     } } (四)优缺点
  优点:
  毫秒数在高位,自增序列在低位,整个ID都是趋势递增的。不依赖数据库等第三方系统,以服务的方式部署,稳定性更高,生成ID的性能也是非常高的。可以根据自身业务特性分配bit位,非常灵活。
  缺点:
  依赖机器时钟,如果机器时钟回拨,会导致重复ID生成在单机上是递增的,但是由于设计到分布式环境,每台机器上的时钟不可能完全同步,有时候会出现不是全局递增的情况(此缺点可以认为无所谓,一般分布式ID只要求趋势递增,并不会亚格要求递增,90%的需求都只要求趋势递增)
  缺点的解决方案
  可以参照以下两个来进行机器时钟的同步 百度开源的分布式唯一ID生成器UidGenerator Leaf--美团点评分布式ID生成系统
  作者:zoeil
  来源:blog.csdn.net/m0_62946761/article/details/129033121
  点击关注,带你了解更多

维生素也会伤肝?这4种维生素,别盲目当成保健品来吃有的人看似很养生,但方法不恰当,会给身体带来伤害,特别是把维生素当饭吃的人,无形中会获取过量引发健康问题。维生素虽说是人体需要的营养物质,但也并非补充量越多越好。不同维生素作用不一云顶之弈神龙风暴史诗级加强,电一王者把把李青把把分前言大家好,我是小嗨。新版本阵容推荐终于来了,今天小嗨就给大家分享第一套新赛季上分阵容爆杀李青(阵容一图流在文章后)阵容组成卡尔玛瑟提伊泽瑞尔奇亚娜卡莎李青沃利贝尔格雷福斯亚索阵容尿液黄,味道还大?可能是身体在向你报告这4件事补充足够水分,经过循环和代谢肾脏可以发挥作用把产生的代谢废物,多余水分的排泄掉,因此白天排尿四到六次,夜间少于两次,属于健康的标志。但许多疾病来袭会通过尿液的颜色,气味等改变发出警唐家河出现六不像,藏在树丛中,身体泛金光,稍不留神会怼人位于我国西部地区的大熊猫国家公园,属于我国宣布设立的第一批国家公园,也是占地面积最大物种多样性最高的国家公园之一,其中里面最有名的物种就是大熊猫。不过由于大熊猫是伞护种,而且伞护作吃肉不如吃豆!建议大家秋天常吃3种豆,高钾高钙,多吃身体好民间有每天吃豆三钱,何需服药连年的说法,其实根据现代医学研究表明,大豆中含有蛋白质钙钾铁等多种营养物质,常吃豆类食物能提高身体免疫力,更强健。可一日无肉,不可一日无豆,建议大家秋天脾虚的人,可以多吃这4种食物,有利于脾脏健康脾虚属于中医病症的一种,脾胃功能变差,消化无法保持良好,还会让代谢废物,湿气等不断累积,进而引发各种症状。许多疾病根源也是脾虚没有正确调理,因此,有这种情况的人应该重视,选择那些有健康是走出来的是非是说出来的1hr那回市上开个相当隆重的大会,让穿正装。男人么,西装,领带,白衬衣,皮鞋,突然发现西装前面的扣子扣不上了。用劲扣上,也抽扯得前襟不是前襟,肩不是肩的,皱得像老汉脸。老鱼惊呼,我魔都周边最孤独的小岛,仅1国人知道江南的初秋明媚而风雅山水为伴清风相随此时最惬意的事莫过于寻一座小岛去吹吹湖风的风听听自然的声音漫步在岛上静静感受慢下来的生活而在太湖之滨就有一处神奇的小岛它像是被上帝遗忘的角落至今怎样治疗神经衰弱?怎样治疗神经衰弱?神经衰弱的治疗和预防是结合在一起的,必须把消除病因和消除症状结合起来。神经衰弱既然主要是精神因素引起的,因此消除病因也必须精神治疗为主,引导病人用辩证唯物主义的观董洁造型大翻车!一身刺绣薄纱裙却穿出满满风尘味,清纯气质全无头条创作挑战赛如果要票选时尚界最让人割舍不下的经典单品,裙装应该能够占据前三名。裙装由于风格多样,在咱们日常搭配中的出镜率只高不低,但是流行不代表着就是百搭,不同面料颜色元素搭配之索菲撒切尔拍摄大片,穿浅绿色网格纱裙身材曼妙,高挑有型近日,索菲撒切尔在户外拍摄大片,身穿浅绿色网格纱裙身材曼妙,高挑有型。索菲撒切尔(SophieThatcher)是一名出色的女演员,这次拍外景很美,她站在大树下,很有夏季的风格,剪
东莞证券IPO行贿判刑,与东莞前首富纠葛15年撰文巨嘴鸟大王2月24日,东莞证券IPO上会,接受发审委审核。若顺利通过,A股券商阵营将扩至49家。东莞证券于1988年6月成立。2008年,东莞证券就已提出争取年内改制成股份公司东莞证券IPO行贿判刑,与东莞前首富纠葛15年撰文巨嘴鸟大王2月24日,东莞证券IPO上会,接受发审委审核。若顺利通过,A股券商阵营将扩至49家。东莞证券于1988年6月成立。2008年,东莞证券就已提出争取年内改制成股份公司iPhone14不支持屏幕下指纹识别功能,苹果计划已经取消iPhone14放弃屏下解锁在之前,有不少消息表示苹果将会在iPhone14上搭载更加成熟的屏幕下解锁方案,可能是指纹识别,也可能是屏下面容识别。但是据最新消息来看,苹果已经取消了iPhone14不支持屏幕下指纹识别功能,苹果计划已经取消iPhone14放弃屏下解锁在之前,有不少消息表示苹果将会在iPhone14上搭载更加成熟的屏幕下解锁方案,可能是指纹识别,也可能是屏下面容识别。但是据最新消息来看,苹果已经取消了七个坏习惯让胃痛找上你,看手机排第一名!护胃锦囊快收好胃痛在我们的日常生活中,已经是一种很常见的症状了,不管是不规律的饮食,还是不干净的食物,又或者是吃得太凉太辣太饱,都有可能引起胃痛。这种时候,大家都会选择忍一忍,或者是自己买点胃药七个坏习惯让胃痛找上你,看手机排第一名!护胃锦囊快收好胃痛在我们的日常生活中,已经是一种很常见的症状了,不管是不规律的饮食,还是不干净的食物,又或者是吃得太凉太辣太饱,都有可能引起胃痛。这种时候,大家都会选择忍一忍,或者是自己买点胃药字节跳动员工猝死?当事人妻子怀孕两个月,房贷是否需要继续还?2月22日深夜,脉脉上字节跳动同事圈板块,一则字节(字节跳动)又猝死一位,妻子怀孕两个月,惨的消息被广泛传开。图脉脉随着热度不断发酵,更多细节被曝出,经由这位妻子在社交平台的发声,字节跳动员工猝死?当事人妻子怀孕两个月,房贷是否需要继续还?2月22日深夜,脉脉上字节跳动同事圈板块,一则字节(字节跳动)又猝死一位,妻子怀孕两个月,惨的消息被广泛传开。图脉脉随着热度不断发酵,更多细节被曝出,经由这位妻子在社交平台的发声,1克就有5亿霉菌,喝普洱就是在喝脏水?普洱茶真的细菌爆表吗?随着人们生活水平的不断提高,在日常生活当中,喜欢饮茶养生的读者越来越多了。这不仅让大家享受到了品质生活,而且还获得了充足的营养,也是非常不错的选择。我国的茶文化历史非常悠久,截止到熬夜族该怎么拯救熊猫眼?常使用化妆品,尤其是美白化妆品,一些重金属离子或深色素微粒渗透到眼皮内就会形成黑眼圈,人体各器官以及人体的细胞都会逐渐衰退,眼睛周围的皮肤细胞也会慢慢老化,也是引起黑眼圈的原因,血走遍云南普洱茶山之云县第三十七章浪坝山古茶园上一章我给朋友们大概介绍了一下云县各乡镇的古茶树,今天我给朋友们介绍一下涌宝镇的浪坝山古茶树群落。浪坝山村委会浪坝山地处云南澜沧江西岸,属于涌宝镇的村民小组,