在分布式系统中,全局唯一ID是一个常见的需求。无论是分库分表后的主键冲突,还是订单号、用户ID等需要唯一标识的场景,都离不开一个可靠的分布式ID生成器。本文将带你了解分布式ID的基本要求,并梳理多种实现方案,从简单的数据库自增到高性能的雪花算法,最后介绍各大厂的开源组件。
分布式ID是指在分布式环境下生成的全局唯一标识符。典型应用场景包括:
一个合格的分布式ID生成器通常需要满足以下几点:

使用MySQL的自增主键来充当分布式ID。创建一张专门用于生成ID的表,每次插入一条记录后获取返回的主键ID。
CREATE DATABASE `SEQ_ID`;
CREATE TABLE SEQID.SEQUENCE_ID (
id bigint(20) unsigned NOT NULL auto_increment,
value char(10) NOT NULL default '',
PRIMARY KEY (id)
) ENGINE=MyISAM;
INSERT INTO SEQUENCE_ID(value) VALUES ('values');优点:简单、天然有序。
缺点:单点故障风险、并发性能差、数据库写入压力大,且ID可反推出订单数量等敏感信息。
为解决单点故障,可以采用多主模式,部署多个MySQL实例独立生成自增ID。通过设置不同的起始值和步长避免重复(以两个节点为例):
-- MySQL实例1
set @@auto_increment_offset = 1; -- 起始值
set @@auto_increment_increment = 2; -- 步长
-- MySQL实例2
set @@auto_increment_offset = 2; -- 起始值
set @@auto_increment_increment = 2; -- 步长优点:缓解单点并发压力。
缺点:不利于动态扩容,新增节点时需处理起始值冲突,甚至可能停机调整。
号段模式的核心思想是批量获取自增ID:每次从数据库取出一个ID范围(如(1,1000]),然后在内存中递增分配,用完后再去数据库获取新的号段。
表结构示例:
CREATE TABLE id_generator (
id int(10) NOT NULL,
max_id bigint(20) NOT NULL COMMENT '当前最大id',
step int(20) NOT NULL COMMENT '号段的步长',
biz_type int(20) NOT NULL COMMENT '业务类型',
version int(20) NOT NULL COMMENT '版本号',
PRIMARY KEY (`id`)
);
INSERT INTO `id_generator` (`id`, `max_id`, `step`, `version`, `biz_type`)
VALUES (1, 0, 100, 0, 101);获取号段的操作:
-- 查询当前号段
SELECT `max_id`, `step`, `version` FROM `id_generator` WHERE `biz_type` = 101;
-- 更新并获取新号段(乐观锁)
UPDATE id_generator
SET max_id = max_id + step, version = version + 1
WHERE version = 0 AND `biz_type` = 101;优点:相比每次获取都访问数据库,大幅减小数据库压力;即使数据库短暂故障,服务仍可使用已缓存的号段继续运行。
缺点:服务器重启或故障可能导致ID不连续。
优化扩展:可以将多主模式与号段模式结合,先为每个节点分配大区间(如节点1以10开头,节点2以11开头),再在每个节点内部使用号段批量获取。此外,引入双缓存机制(预加载下一个号段)可进一步提升性能。
Java中可通过UUID.randomUUID()生成,去掉连字符后得到一个32位随机字符串。
public static void main(String[] args) {
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
System.out.println(uuid);
}优点:实现简单、唯一性有保障。
缺点:不具备趋势递增(UUID v7版本已有所改善),导致数据库写入性能差、查询效率低;16字节的存储长度占用较大空间。
UUID的演进可以参考:UUID版本介绍
Twitter开源的分布式ID生成算法,将64-bit(Java中用long类型存储)划分为多个部分:
| 1 bit(未使用) | 41 bit(毫秒时间戳) | 10 bit(机器ID) | 12 bit(序列号) |
|---|---|---|---|
理论上一台机器在一个毫秒内可生成4096个不重复ID,且趋势递增。
优点:不依赖数据库等第三方系统,纯内存计算,性能极高;可根据业务需求灵活调整bit分配。
缺点:强依赖机器时钟。若发生时钟回拨,可能产生重复ID或导致服务不可用(官方简单抛错处理,回拨期间服务暂停)。
更详细的介绍参考:雪花算法解析
一种替代方案,详情可参考:薄雾算法介绍
利用Redis的INCR命令实现原子递增:
127.0.0.1:6379> set seq_id 1 # 初始化
OK
127.0.0.1:6379> incr seq_id # 原子递增,返回新值
(integer) 2需要注意持久化配置和极端情况下的ID重复问题。
基于Zookeeper的znode数据版本号生成序列号(32位或64位),客户端可用作唯一ID。由于高度依赖Zookeeper且为同步API调用,高并发场景下性能不理想。
| 组件 | 公司 | 地址 |
|---|---|---|
| Tinyid | 滴滴 | https://github.com/didi/tinyid |
| UidGenerator | 百度 | https://github.com/baidu/uid-generator |
| Leaf | 美团 | https://github.com/Meituan-Dianping/Leaf |
| Seqsvr | 腾讯 | https://github.com/uidgen/seqsvr |
延伸阅读:
选择分布式ID方案时,需要根据业务场景权衡性能、可用性、有序性、复杂度等因素:
没有完美的方案,只有最契合业务场景的选择。希望本文能帮助你理清分布式ID的设计思路,在实际项目中做出更合理的决策。
]]>之前使用的是云服务器是腾讯与的2核4G服务器,但是由于最开始购买时只买了一年,续费时价格太贵,因此转到阿里云,可以有四年每年99元的2核2G服务器可以白嫖~
迁移过程大概分为两步:站点数据迁移和站点备案迁移
原来的博客使用wordpress框架,但是wordpress框架功能齐全、有些臃肿,因此这里换成了更精简的typecho框架。
导出wordpress数据库并在新服务器中导入
还原wordpress中的图片附件到typecho中
update typecho_contents set text=replace(text,'wp-content/uploads','usr/uploads')
update typecho_contents set text=replace(text,'wordpree站点url','typecho站点url')做法是现在新服务器上安装docker,然后迁移旧服务器上的docker挂载文件夹到新服务器相同位置,最后在新服务器启动容器。参考链接:https://zhuanlan.zhihu.com/p/643367054
这里我主要使用了两个容器用于存储电子书和笔记
为了方便使用,计划将域名和服务器都转移到阿里云。因为服务器需要在所在服务商处备案,因此还需要在阿里云备案,主要参考了这篇博客:https://www.zuozuovera.com/posts/1644/。
]]>针对C++程序,重新下载代码编译;
重新配置Python环境主要经历了以下步骤:
1. 下载miniconda安装程序并安装;
2. WSL2环境迁移到服务器中,这里选择直接打包WSL2下面的虚拟环境目录并到服务器相应目录下解压,参考了教程https://blog.csdn.net/qq_45893319/article/details/122226053;
3. 直接打包的环境,无法使用pip的问题,可以通过修改pip文件解决,参考教程https://blog.csdn.net/qq_40933913/article/details/127907916
4. 环境迁移后发现在迁移的环境中无法使用clear命令,原因是迁移过来的环境中clear文件有问题。解决方案如下:
which clear,然后将clear地址重命名,下次再clear时会生成新的。mv /home/xxx/.conda/envs/yolox/bin/clear /home/xxx/.conda/envs/yolox/bin/clear_old
参考教程https://blog.csdn.net/ffriend/article/details/126680223。
由于服务器离线,使用vscode连接时无法在远程服务器上下载vscode-server,这里需要手动下载一下。步骤如下
1. 查看本地vscode的commit id:帮助-关于,复制commit id
2. 本地下载vscode-server
wget https://update.code.visualstudio.com/commit:${commit_id}/server-linux-x64/stable
# 注意把:${commit_id}替换成对应的Commit ID
rm ~/.vscode-server/bin/* -rf #把$HOME/.vscode-server/bin下的内容删干净,防止出错
cd ~/.vscode-server/bin
tar -zxf vscode-server-linux-x64.tar.gz
mv vscode-server-linux-x64 ${commit_id} # 注意把:${commit_id}替换成对应的Commit ID
参考教程https://blog.csdn.net/Demo_Null/article/details/110873673,主要是编译安装screen和ncurses两个可执行程序,这里需要管理员权限,负责无法安装到默认的安装位置。
1、启动共享窗口:screen -S 名称
2、查看当前所有共享会话:screen -ls
3、进入共享会话:screen -r 名称
4、退出共享会话:ctrl +a +d
在设置中选择“插入鼠标后禁用触摸板”选项后,将鼠标拔出后触摸板仍然无法使用,出现这种问题后
1. 关闭“插入鼠标后禁用触摸板”选项,插入鼠标观察触摸板是否可以使用,如果不能使用那么触摸板可能损坏,需要进一步排查;如果可以使用,那么可能是因为设备管理器中出现了虚拟鼠标;
2. 如果是第一步的第二种情况,需要在设备管理器中禁用第一个鼠标选项,如下图所示:

购买腾讯云清量2核4G服务器直达链接
这里选择了Ubuntu server 20.04,启动镜像后设置远程登录(远程登录->密码/密钥登录->重置密码),需要注意这里的用户需要系统中已经存在,默认已经存在一个用户ubuntu,这里我们直接使用该用户。
配置好后可以本地使用Mobaxterm登录云服务器,将云服务器当作Ubuntu虚拟机使用。
网站搭建参考了博客https://blog.csdn.net/weixin_36338224/article/details/109105047。
下载Kratos主题并上传替换原有主题,在外观里设置。
用于Wordpress
安装WP Editor.md插件,在wordpress中使用markdown编辑。
安装Simple MathJax插件,实现对latex公示的支持,需要注意的是这里行内公式使用\(..\),例如$\sigma$,行间公式使用$$..$$,例如$$\sigma$$。