关于uuid:存储拆分后如何解决唯一主键问题

在单库单表时,业务 ID 能够依赖数据库的自增主键实现,当初咱们把存储拆分到了多处,如果还是用数据库的自增主键,就会呈现主键反复的状况。 所以咱们不得不面对的一个抉择,就是ID生成器,应用一个惟一的字符串,来标识一条残缺的记录。 这时候,不能应用md5或者sha1来对整个记录做摘要,因为咱们后续还要改变这个记录。也不能应用单机的计数器,因为计数器容易重启清零,也会存在多台机器上的数值反复,这违反了无状态服务的建设指标。 UUID尽管UUID在大多数语言中都有相干的类库,但除非迫不得以,咱们个别不会应用它。UUID尽管不会反复,但它十分的长,长的让人望而却步。 规范的UUID有5个局部组成:8-4-4-4-12,一共32个十六进制字符。因而,一共是128位。当把UUID作为数据库的索引时,会因为它没有程序性造成索引的随机散布和因为数据量微小造成查问性能升高。 且无序会造成每一次UUID数据的插入都会对主键的b+树进行很大的批改, 会产生离散 IO,从而产生性能瓶颈。同时,UUID也是不可读的,如果你把它打印在纸质的订单上,并不是一个好的主见。UUID同时还有信息安全的隐患,它的数据计算里有MAC地址的参加,比拟出名的是,曾被用于寻找梅丽莎病毒的制作者地位。 MySQL8当前MySQL 8.0 推出了函数 UUID_TO_BIN,它能够把 UUID 字符串: 通过参数将工夫高位放在最前,解决了 UUID 插入时乱序问题;去掉了无用的字符串"-",精简存储空间;将字符串其转换为二进制值存储,空间最终从之前的 36 个字节缩短为了 16 字节。同时还提供了 BIN_TO_UUID,反对将二进制值反转为 UUID 字符串,不必放心 UUID 的性能和存储占用的空间问题,相干的插入性能测试,后果如下表所示: 因为UUID_TO_BIN转换为的后果是16 字节,仅比自增 ID 减少 8 个字节,最初存储占用的空间也仅比自增大了 3G。 而且因为 UUID 能保障全局惟一,因而应用 UUID 的收益远远大于自增ID。在海量并发的互联网业务场景下,更举荐 UUID 这样的全局惟一值做主键。 但请牢记:分布式数据库架构,仅用 UUID 做主键仍然是不够的。 数据库自增ID当数据量宏大时,在数据库分库分表后,数据库自增id不能满足惟一id来标识数据;因为每个表都按本人节奏自增,会造成id抵触,无奈满足需要 革新工夫戳如果你是单机利用,那么应用工夫戳没什么问题,即便不必纳秒,应用毫秒也是足够的。但在分布式环境上面,工夫戳同样不是一个好的抉择。 即便你在机器装置了 ntpd 工夫同步,但因为网络和机器的差别,计算机的时钟总是存在差别,你的工夫戳总会呈现反复。为了解决这个问题,你须要减少一些其余的标识,比方机器的ID,或者更多细分的信息缩小工夫的碰撞。 这种自定义的ID生成器,只适宜特定的业务,做着做着你就会发现,它实质上是雪花算法的变种。 全局ID生成器服务能够设计一个全局 ID 生成器服务,每次找服务索要主键,这样尽管能够在业务间实现全局惟一,然而齐全依赖全局 ID 生成服务,依赖性大,服务一旦宕机,会影响所有相干依赖服务。 例如应用Redis的计数器,原子性自增,益处在于应用内存,并发性能好,但存在数据失落;自增数据量泄露的问题 雪花算法Twitter 雪花算法生成后是一个 64bit 的 long 型的数值,默认字符串长度是19位,它分为4个局部,根本放弃了自增 蕴含四个组成部分 不应用:1bit,最高位是符号位,0 示意正,1 示意负,固定为 0 ...

February 21, 2023 · 1 min · jiezi

关于uuid:js-生成UUID的几种方法

简介: UUID(Universally Unique IDentifier) 全局惟一标识符。UUID是一种由算法生成的二进制长度为128位的数字标识符。UUID的格局为“xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx”,其中的 x 是 0-9 或 a-f范畴内的一个32位十六进制数。在现实状况下,任何计算机和计算机集群都不会生成两个雷同的UUID。 1.第一种 function guid() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); });}guid() // "a1ca0f7b-51bd-4bf3-a5d5-6a74f6adc1c7"2.第二种 function uuid() { var s = []; var hexDigits = "0123456789abcdef"; for (var i = 0; i < 36; i++) { s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1); } s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010 s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01 s[8] = s[13] = s[18] = s[23] = "-"; var uuid = s.join(""); return uuid;}uuid() // "ffb7cefd-02cb-4853-8238-c0292cf988d5"3.第三种 ...

May 25, 2022 · 2 min · jiezi

分布式唯一-ID-之-Snowflake-算法

一、Snowflake 简介1.1 什么是 SnowflakeSnowflake is a service used to generate unique IDs for objects within Twitter (Tweets, Direct Messages, Users, Collections, Lists etc.). These IDs are unique 64-bit unsigned integers, which are based on time, instead of being sequential. The full ID is composed of a timestamp, a worker number, and a sequence number. When consuming the API using JSON, it is important to always use the field id_str instead of id. This is due to the way Javascript and other languages that consume JSON evaluate large integers. If you come across a scenario where it doesn’t appear that id and id_str match, it’s due to your environment having already parsed the id integer, munging the number in the process. —— developer.twitter.comSnowflake(雪花) 是一项服务,用于为 Twitter 内的对象(推文,直接消息,用户,集合,列表等)生成唯一的 ID。这些 IDs 是唯一的 64 位无符号整数,它们基于时间,而不是顺序的。完整的 ID 由时间戳,工作机器编号和序列号组成。当在 API 中使用 JSON 数据格式时,请务必始终使用 id_str 字段而不是 id,这一点很重要。这是由于处理JSON 的 Javascript 和其他语言计算大整数的方式造成的。如果你遇到 id 和 id_str 似乎不匹配的情况,这是因为你的环境已经解析了 id 整数,并在处理的过程中仔细分析了这个数字。 ...

November 4, 2019 · 6 min · jiezi

MySQL主从同步中的serverid

当我们搭建MySQL集群时,自然需要完成数据库的主从同步来保证数据一致性。而主从同步的方式也分很多种,一主多从、链式主从、多主多从,根据你的需要来进行设置。但只要你需要主从同步,就一定要注意server-id的配置,否则会出现主从复制异常。 在控制数据库数据复制和日志管理中,有两个重要的配置:server-id和server-uuid,他们会影响二进制日志文件记录和全局事务标识。 server-id配置 当你使用主从拓扑时,一定要对所有MySQL实例都分别指定一个独特的互不相同的server-id。默认值为0,当server-id=0时,对于主机来说依然会记录二进制日志,但会拒绝所有的从机连接;对于从机来说则会拒绝连接其它实例。 MySQL实例的server-id是一个全局变量,可以直接查看: mysql> show variables like '%server_id%';+---------------+-----------+| Variable_name | Value |+---------------+-----------+| server_id | 171562767 |+---------------+-----------+1 row in set (0.00 sec)我们可以在线直接修改全局变量server-id,但不会立即生效,所以修改后记得重启服务。而重启后又会重新读取系统配置文件配置,导致刚才的修改失效,因此建议修改配置文件后重启服务而不是在线修改: #my.cnf[mysqld]#replicationlog-bin=mysql-binserver-id=171562767sync_binlog=1binlog-ignore-db=mysqlbinlog-ignore-db=information_schemaserver-id用途server-id用于标识数据库实例,防止在链式主从、多主多从拓扑中导致SQL语句的无限循环: 标记binlog event的源实例过滤主库binlog,当发现server-id相同时,跳过该event执行,避免无限循环执行。如果设置了replicate-same-server-id=1,则执行所有event,但有可能导致无限循环执行SQL语句。我们用两个例子来说明server-id为什么不要重复: 当主库和备库server-id重复时由于默认情况replicate-same-server-id=0,因此备库会跳过所有主库同步的数据,导致主从数据的不一致。 当两个备库server-id重复时会导致从库跟主库的连接时断时连,产生大量异常。根据MySQL的设计,主库和从库通过事件机制进行连接和同步,当新的连接到来时,如果发现server-id相同,主库会断开之前的连接并重新注册新连接。当A库连接上主库时,此时B库连接到来,会断开A库连接,A库再进行重连,周而复始导致大量异常信息。 生成server-id的规则既然server-id不能相同,而当我们有10个实例时,怎么保证每个都不同呢?有几种常用的方法: 随机数时间戳IP地址+端口在管理中心集中分配,生成自增ID上面的这些方法都可以,但是注意不要超过了最大值2^32-1,同时值最好>2。我采用的方法是IP地址后两位+本机MySQL实例序号,但如果是通过docker来进行管理多实例时,这个怎么生成大家可以想下有没有什么优美的解决方案。 server-uuid配置 MySQL服务会自动创建并生成server-uuid配置: 读取${data_dir}/auto.cnf文件中的UUID如果不存在,自动创建文件和生成新的UUID并读取shell> cat ~/mysql/data/auto.cnf[auto]server-uuid=fd5d03bc-cfde-11e9-ae59-48d539355108这个auto.cnf配置风格类似于my.cnf,但这个文件只包含一个auto配置块和一行server-uuid配置。它是自动创建的,因此不要修改它的内容。 在主从拓扑中,主从可以知道互相的UUID,在主机上使用show slave hosts,在从机上使用show slave status查看Master_UUID字段。 server-uuid参数并不能取代server-id,他们有不同的作用。当主从同步时如果主从实例的server-uuid相同会报错退出,不过我们可以通过设置replicate-same-server-id=1来避免报错(不推荐)。 参考资料17.1.6 Replication and Binary Logging Options and Variables:https://dev.mysql.com/doc/ref...如何生成唯一的server Id:http://ju.outofmemory.cn/entr...

September 7, 2019 · 1 min · jiezi

使用java9的uuid生成方式,让uuid生成速度提升一个档

简介UUID 的目的,是让分布式系统中的所有元素,都能有唯一的辨识信息,而不需要通过中央控制端来做辨识信息的指定。uuid 常用场景IOT 设备,设备号;网站 sessionid,cookie 用户id;数据库主键id;uuid 生成工具hutool Java工具包集mica 基于 Spring、 java8 微服务工具集压测代码测试基于 JMH,是专门用于代码微基准测试的工具套件,基于方法层面的基准测试,精度可以达到微秒级。压测代码源码存放于 github,感兴趣的朋友可以:https://github.com/lets-mica/mica-jmhjdk8UUId@Benchmarkpublic String jdk8UUId() { return UUID.randomUUID().toString();}jdk8ThreadLocalRandomUUId@Benchmarkpublic String jdk8ThreadLocalRandomUUId() { ThreadLocalRandom random = ThreadLocalRandom.current(); UUID uuid = new UUID(random.nextInt(), random.nextInt()); return uuid.toString();}hutoolFastSimpleUUID@Benchmarkpublic String hutoolFastSimpleUUID() { return IdUtil.fastSimpleUUID();}micaUUId@Benchmarkpublic String micaUUId() { return StringUtil.getUUID();}压测环境OS: macOS MojaveCPU: 2.8 GHz Intel Core i5RAM: 8 GB 1600 MHz DDR3JVM: Oracle 1.8.0_201 64 bits压测结果BenchmarkScoreErrorUnitsjdk8UUId734.59517.220ops/msjdk8ThreadLocalRandomUUId3224.75932.107ops/mshutoolFastSimpleUUID3619.74867.195ops/msmicaUUId(java9 方式)12375.405241.879ops/ms说明:每毫秒生成的 uuid 数,得分越高越好。总结mica 由于参考(copy) java9 的 uuid 生成方式性能强劲,是 jdk8 ThreadLocalRandom 和 hutool FastSimpleUUID 的3到4倍的。由于 uuid 的使用场景一般都需要高性能高并发,大家在使用的时候可以尝试使用 java9+ 或者参考他的算法去实现。开源推荐Spring boot 微服务高效开发 mica 工具集:https://gitee.com/596392912/micaAvue 一款基于vue可配置化的神奇框架:https://gitee.com/smallweigit/avuepig 宇宙最强微服务(架构师必备):https://gitee.com/log4j/pigSpringBlade 完整的线上解决方案(企业开发必备):https://gitee.com/smallc/SpringBladeIJPay 支付SDK让支付触手可及:https://gitee.com/javen205/IJPay关注我们扫描上面二维码,更多精彩内容每天推荐! ...

March 30, 2019 · 1 min · jiezi