@
最近在项目中用了UUID的方式生成主键,一开始只是想把这种UUID的方式生成主键记录下来,在查阅资料的过程中,又有了一些新的认识和思考。
唯一标识表中每行的一个列(或一组列)称为主键。主键用来表示一个特定的行。
除了满足MySQL强制实施的规则(主键不可重复;一行中主键不可为空)之外,主键的设计和应用应当还遵守以下公认的原则:
- 不更新主键列中的值;
- 不重用主键列的值;
- 不在主键列中使用可能会更改的值。(例如,如果使用一个
名字作为主键以标识某个供应商,当该供应商合并和更改其
名字时,必须更改这个主键。)
使用数据库的自动增长(auto_increment),是比较简单和常见的ID生成方案,数据库内部可以确保生成id的唯一性。
优点:
1、数据库自动编号,速度快,而且是增量增长,聚集型主键按顺序存放,对于检索非常有利。
2、 数字型,占用空间小,易排序,在程序中传递方便。
缺点:
1、不支持水平分片架构,水平分片的设计当中,这种方法显然不能保证全局唯一。
2、对数据库有依赖,每种数据库可能实现不一样,数据库切换时候,涉及到代码的修改,不利于扩展
结论:
自增id做主键适用于非分布式架构。
550e8400-e29b-41d4-a716-446655440000
到目前为止业界一共有5种方式生成UUID,详情可见IETF发布的UUID规范A Universally Unique IDentifier (UUID) URN Namespace 。
优点:
性能非常高:本地生成,没有网络消耗。
缺点:
1、不易于存储:UUID太长,16字节128位,通常以36长度的字符串表示,很多场景不适用。
2、信息不安全:基于MAC地址生成UUID的算法可能会造成MAC地址泄露,这个漏洞曾被用于寻找梅丽莎病毒的制作者位置。
3、ID作为主键时在特定的环境会存在一些问题,比如需要排序的时候——UUID是无序的。
4、MySQL官方有明确的建议主键要尽量越短越好,36个字符长度的UUID不符合要求。
5、对MySQL索引不利:作为数据库主键,在InnoDB引擎下,UUID的无序性可能会引起数据位置频繁变动,严重影响性能。
关于MySQL 使用自增ID主键和UUID 作为主键的性能比较可以查看参考【8】。
结论:
1、uuid做主键适用于小规模分布式架构用。
2、在使用uuid作为主键的时候,最好设计createtime(创建时间)列和modifytime(修改时间)列以应付可能的排序等场景。
Twitter的snowflake算法的核心把时间戳,工作机器id,序列号组合在一起。
除了最高位bit标记为不可用以外,其余三组bit占位均可浮动,看具体的业务需求而定。默认情况下41bit的时间戳可以支持该算法使用到2082年,10bit的工作机器id可以支持1023台机器,序列号支持1毫秒产生4095个自增序列id。
具体可以查看:https://github.com/twitter-archive/snowflake.git (但是最近一次的提交是6年前,显示已经停止了对初始版snowflake的支持)
源码如下:
优点:
1、毫秒数在高位,自增序列在低位,整个ID都是趋势递增的。
2、 不依赖数据库等第三方系统,以服务的方式部署,稳定性更高,生成ID的性能也是非常高的。
3、可以根据自身业务特性分配bit位,非常灵活。
缺点:
强依赖机器时钟,如果机器上时钟回拨,会导致发号重复或者服务会处于不可用状态。
结论:
用自建的id生成器做主键适用于大规模分布式架构
参考:
【1】:红心李 :MySQL主键设计
【2】:Uncle Nucky :MySQL数据库主键设计原则
【3】:ellis:设计套路:Mysql主键的选取
【4】:路人甲Java:分布式系统生成唯一id常见方案
【5】:《MySQL必知必会》
【6】:美团技术团队:Leaf——美团点评分布式ID生成系统
【7】:UUID performance in MySQL?
【8】:alex.shu:MySQL 使用自增ID主键和UUID 作为主键的优劣比较详细过程(从百万到千万表记录测试)
【9】:咖啡拿铁:如果再有人问你分布式ID,这篇文章丢给他
【10】:漫漫路:Twitter-Snowflake,64位自增ID算法详解
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ri-ji/14779.html