优点:高性能,低延迟;独立的应用;按时间有序。
缺点:需要独立的开发和部署。
4、Redis生成ID
当使用数据库来生成ID性能不够要求的时候,我们可以尝试使用Redis来生成ID。这主要依赖于Redis是单线程的,所以也可以用生成全局唯一的ID。可以用Redis的原子操作INCR和INCRBY来实现。
可以使用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
比较适合使用Redis来生成每天从0开始的流水号。比如订单号=日期+当日自增长号。可以每天在Redis中生成一个Key,使用INCR进行累加。
优点:
不依赖于数据库,灵活方便,且性能优于数据库。
数字ID天然排序,对分页或者需要排序的结果很有帮助。
使用Redis集群也可以防止单点故障的问题。
缺点:
如果系统中没有Redis,还需要引入新的组件,增加系统复杂度。
需要编码和配置的工作量比较大,多环境运维很麻烦,
在开始时,程序实例负载到哪个redis实例一旦确定好,未来很难做修改。
5、Flicker的解决方案
因为MySQL本身支持auto_increment操作,很自然地,我们会想到借助这个特性来实现这个功能。
Flicker在解决全局ID生成方案里就采用了MySQL自增长ID的机制(auto_increment + replace into + MyISAM)。
6、还有其他一些方案,比如京东淘宝等电商的订单号生成。因为订单号和用户id在业务上的区别,订单号尽可能要多些冗余的业务信息,比如:
滴滴:时间+起点编号+车牌号
淘宝订单:时间戳+用户ID
其他电商:时间戳+下单渠道+用户ID,有的会加上订单第一个商品的ID。
而用户ID,则要求含义简单明了,包含注册渠道即可,尽量短。
四、最终方案
最终我们选择了以flicker方案为基础进行优化改进。具体实现是,单表递增,内存缓存号段的方式。
首先建立一张表,像这样:
SEQUENCE_GENERATOR_TABLE
id stub
1 192.168.1.1
其中id是自增的,stub是服务器ip
因为新数据库采用mysql,所以使用mysql的独有语法 replace to来更新记录来获得唯一id,例如这样:
REPLACE INTO SEQUENCE_GENERATOR_TABLE (stub) VALUES (“192.168.1.1”);
再用
SELECT id FROM SEQUENCE_GENERATOR_TABLEWHERE stub = “192.168.1.1”;
把它拿回来。
到上面为止,我们只是在单台数据库上生成ID,从高可用角度考虑,接下来就要解决单点故障问题。
这也就是为什么要有这个机器ip字段呢?就是为了防止多服务器同时更新数据,取回的id混淆的问题。
所以,当多个服务器的时候,这个表是这样的:
id stub
5 192.168.1.1
2 192.168.1.2
3 192.168.1.3
4 192.168.1.4
每台服务器只更新自己的那条记录,保证了单线程操作单行记录。
这时候每个机器拿到的分别是5,2,3,4这4个id。
至此,我们似乎解决这个服务器隔离,原子性获得id的问题,也和flicker方案基本一致。
但是追根溯源,在原理上,方案还是依靠数据库的特性,每次生成id都要请求db,开销很大。我们对此又进行优化,把这个id作为一个号段,而并不是要发出去的序列号,并且这个号段是可以配置长度的,可以1000也可以10000,也就是对拿回来的这个id放大多少倍的问题。
OK,我们从DB一次查询操作的开销,拿回来了1000个用户id到内存中了。
现在的问题就是要解决同一台服务器在高并发场景,让大家顺序拿号,别拿重复,也别漏拿。
这个问题简单来说,就是个保持这个号段对象隔离性的问题。
AtomicLong是个靠谱的办法。
当第一次拿回号段id后,扩大1000倍,然后赋值给这个变量atomic,这就是这个号段的第一个号码。
atomic.set(n * 1000);
并且内存里保存一下最大id,也就是这个号段的最后一个号码
currentMaxId = (n + 1) * 1000;
一个号段就形成了。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
最后总结
ActiveMQ+Kafka+RabbitMQ学习笔记PDF
关于分布式,限流+缓存+缓存,这三大技术(包含:ZooKeeper+Nginx+MongoDB+memcached+Redis+ActiveMQ+Kafka+RabbitMQ)等等。这些相关的面试也好,还有手写以及学习的笔记PDF,都是啃透分布式技术必不可少的宝藏。以上的每一个专题每一个小分类都有相关的介绍,并且小编也已经将其整理成PDF啦
bbitMQ学习笔记PDF
[外链图片转存中…(img-OiibeFmK-1712008727691)]
[外链图片转存中…(img-hSodwYq7-1712008727692)]
[外链图片转存中…(img-gRn3ZHus-1712008727692)]
[外链图片转存中…(img-zvAYFpX9-1712008727692)]
关于分布式,限流+缓存+缓存,这三大技术(包含:ZooKeeper+Nginx+MongoDB+memcached+Redis+ActiveMQ+Kafka+RabbitMQ)等等。这些相关的面试也好,还有手写以及学习的笔记PDF,都是啃透分布式技术必不可少的宝藏。以上的每一个专题每一个小分类都有相关的介绍,并且小编也已经将其整理成PDF啦