分布式全局唯一ID生成方案,成功入职网易月薪35K

本文讨论了使用Redis生成高性能、低延迟的全局ID的方法,包括Redis的原子操作和集群优势,以及与MySQL自增长ID的比较。文章还介绍了分布式技术如ActiveMQ、Kafka和RabbitMQ在ID生成中的应用,以及注意事项和优化方案。
摘要由CSDN通过智能技术生成

优点:高性能,低延迟;独立的应用;按时间有序。

缺点:需要独立的开发和部署。

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开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

最后总结

ActiveMQ+Kafka+RabbitMQ学习笔记PDF

image.png

  • RabbitMQ实战指南

image.png

  • 手写RocketMQ笔记

image.png

  • 手写“Kafka笔记”

image

关于分布式,限流+缓存+缓存,这三大技术(包含:ZooKeeper+Nginx+MongoDB+memcached+Redis+ActiveMQ+Kafka+RabbitMQ)等等。这些相关的面试也好,还有手写以及学习的笔记PDF,都是啃透分布式技术必不可少的宝藏。以上的每一个专题每一个小分类都有相关的介绍,并且小编也已经将其整理成PDF啦
bbitMQ学习笔记PDF

[外链图片转存中…(img-OiibeFmK-1712008727691)]

  • RabbitMQ实战指南

[外链图片转存中…(img-hSodwYq7-1712008727692)]

  • 手写RocketMQ笔记

[外链图片转存中…(img-gRn3ZHus-1712008727692)]

  • 手写“Kafka笔记”

[外链图片转存中…(img-zvAYFpX9-1712008727692)]

关于分布式,限流+缓存+缓存,这三大技术(包含:ZooKeeper+Nginx+MongoDB+memcached+Redis+ActiveMQ+Kafka+RabbitMQ)等等。这些相关的面试也好,还有手写以及学习的笔记PDF,都是啃透分布式技术必不可少的宝藏。以上的每一个专题每一个小分类都有相关的介绍,并且小编也已经将其整理成PDF啦

  • 10
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值