代码编织梦想

概述

在复杂分布式系统中,往往需要对大量的数据和消息进行唯一标识。比如MySQL一般都是采用分库分表的架构,那么我们就需要保证所有数据的ID全局唯一,而不仅仅是在单个MySQL数据库表中唯一。此时一个能生成唯一ID的方案是非常必要的。而此时对于生成的全局ID,我们要考虑方案的几个方面:

  1. 全局唯一
  2. 递增性:由于数据是存储在MySQL上的,MySQL索引以B+树的形式组织,递增的ID可以提高MySQL的性能
  3. 信息安全:外界是否能通过ID判断出系统的一些信息,防止通过ID进行一些恶意的操作
  4. 性能:在如今高并发的环境下,我们需要考虑生成ID的性能

而目前业界生成分布式唯一ID的方案大概有以下几种

  • UUID
  • 数据库发号
    • 主键自增发号
    • 分段发号
  • 随机字符串/随机数
  • Snowflake算法

UUID

最常见的ID生成方案,简单的来说,UUID可以让服务器在不需要任何外界依赖的情况下,基于当前时间、硬件标识等等信息生成的唯一ID。一般表现为16字节的字符串。

优点:

  1. 无任何依赖,无需中心化的服务器
  2. 实现简单
  3. 生成的UUID没有任何可用信息,保护系统信息安全

缺点:

  1. 生成的UUID没有任何可用信息,可读性差
  2. 占用空间太多
  3. UUID字符串,不递增,不适合作为数据库主键,会影响数据库性能

场景:通常可以作为一些临时性唯一标识,例如用户登陆后,生成一个UUID作为登录的SessionID,作为key存储在Redis中,Value是用户相关的信息。

数据库发号

我们可以通过单点数据库发号来实现

根据主键自增发号

直接通过主键自增连续发号,有单机和多机两种方式。

单机数据库主键自增

通过操作数据库中的一张表,插入一条数据后或者该数据的主键ID,用主键ID作为全局的唯一ID

优点:

  1. 实现简单,方便接入,只依赖于数据库
  2. 完全单调递增,有利于数据库性能的提高

缺点:

  1. 性能较低,由于发号依赖于数据库插入数据,所以并发比较低
  2. 易出现单点故障,一旦单机数据库发生宕机,就没法生成ID,系统就无法使用
  3. ID连续,容易泄露信息,比如恶意刷API,比如通过ID推测出系统数据量级

场景:适用于并发量不高的业务

多数据库主键自增

对于多数据库的主键自增,我们要保证所有数据库都不重复,那么就可以给不同数据库设置不同的步长,可以让不同数据库生成的ID不同。

比如说有4台机器,那么就可以设置步长为4

  1. 1 、5、9、13、17
  2. 2、6、10、14、18
  3. 3、7、11、15、19
  4. 4、8、12、16、20

然后业务层通过Hash轮询不同的数据库来获取生成的ID,这样就通过多台数据库完成了发号操作。

在MySQL中设置步长的命令为

alter table <table name> auto_increment= 4;

优点:

  1. 相比单台数据库来说,性能更高,因为可以多台数据库同时发号

缺点:

  1. 实现比较复杂,依赖多台数据库
  2. 不方便扩容

场景:在没有分库分表的框架以前,业务上的分库分表就是使用这种方案来实现的。

分段发号

简单来说,就是用一个数据库表充当发号器,但是并不是用主键自增,而是用一个单独的字段。

字段意义
tag用于区分每种Id应用的业务
max_id记录当前已生成的最大ID
step每次可以获取Id的数量
description描述信息
update_time更新时间

每次使用下面这条语句从数据库获取step数量的id,并且更新max_id的值,将step数量的ID存储在内存中,供业务方通过HTTP,RPC,Client等方式来获取。此处由于多线程并发,所以存在内存中的ID应保证其操作具有线程安全性,比如在Java中应该使用原子类AtomicLong。

UPDATE leaf_alloc SET max_id = max_id + step WHERE tag = #{tag}

该方法也是美团的开源项目Leaf所采用的方式之一。

优点:

  1. 效率较高,生成的效率取决于Step的大小

缺点:

  1. 单点故障问题依旧存在
  2. ID连续,容易出现信息安全问题

场景:适用于系统仅有单台数据库但并发量较高的情况。

Snowflake算法

Snowflake,雪花算法是由Twitter开源的分布式ID生成算法,以划分命名空间的方式将 64-bit位分割成多个部分,每个部分代表不同的含义。而 Java中64bit的整数是Long类型,所以在 Java 中 SnowFlake 算法生成的 ID 就是 long 来存储的。

  • 第1位占用1bit,其值始终是0,可看做是符号位不使用。
  • 第2位开始的41位是时间戳,41-bit位可表示2^41个数,每个数代表毫秒,那么雪花算法可用的时间年限是(1L<<41)/(1000L360024*365)=69 年的时间。
  • 中间的10-bit位可表示机器数,即2^10 = 1024台机器,但是一般情况下我们不会部署这么台机器。如果我们对IDC(互联网数据中心)有需求,还可以将 10-bit 分 5-bit 给 IDC,分5-bit给工作机器。这样就可以表示32个IDC,每个IDC下可以有32台机器,具体的划分可以根据自身需求定义。
  • 最后12-bit位是自增序列,可表示2^12 = 4096个数。

这样的划分之后相当于在一毫秒一个数据中心的一台机器上可产生4096个有序的不重复的ID。但是我们 IDC 和机器数肯定不止一个,所以毫秒内能生成的有序ID数是翻倍的。

优点:

  1. 性能高
  2. ID不连续,保证了信息安全
  3. ID趋势递增,保证了数据库的性能

缺点:

  1. 一般类Snowflake算法会引入注册中心,增加了系统的复杂性
  2. 存在系统时钟回拨导致重复ID的问题,可以通过注册中心解决,保证全局唯一时钟

总结

分布式ID的生成在如今分布式环境下越来越重要了,读者也可以根据文章的几种方式,自己实现一些ID生成的Demo

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_45563088/article/details/129675829

[转]redis2.8从入门到精通文档-爱代码爱编程

版本:V3.1 2014-3-36 (@江南白衣版权所有,转载请保留出处),针对Redis 2.8版。 1. Overview 1.1 资料 <The Little Redis Book> ,最好的入门小册子,可以先于一切文档之前看,免费。作者Antirez的博客,Antirez维护的Redis推特。Redis weekly redis周

quartz调度系统入门和调度高可用实现方案_ywb201314的博客-爱代码爱编程

** 版本:2.2.1 ** Hello world: 调度器: Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); scheduler.start(); 任务详情:任务体实现Job接口 JobDetail job = JobBuilder.newJob(MakeHtm

redis分布式锁的正确实现方式(java版)_bug弄潮儿的博客-爱代码爱编程

阅读文本大概需要3分钟。 本文转自:https://wudashan.cn/2017/10/23/Redis-Distributed-Lock-Implement/ 新课程推荐有需要的购买有返现,新鲜滚热辣,热腾腾的 本文使用第三方开源组件Jedis实现Redis客户端,且只考虑Redis服务端单机部署的场景。 前言 分布式锁一般有三

三分钟带你入门 redis 高可用架构之哨兵-爱代码爱编程

什么是哨兵? 哨兵(Sentinel)是 redis 的高可用性解决方案,前面我们讲的主从复制它是高可用的基础,需要人工介入才能完成故障转移,哨兵可以解决这个问题,在主从复制情况下,当主节点发生故障时,哨兵可以自动的发现故障并且完成故障转移,实现真正的 redis 高可用。在哨兵集群中,哨兵会监视所有的 redis 服务器和其他 sentinel 节点状

使用Redis解决页面并发问题 分布式锁-爱代码爱编程

当并发量提高的时候数据库就支撑不了很高的并发,这时候我们就可以引入redis来做一个数据库的缓存,来减小数据库的压力,当数据库第一次被查询之后,就把数据库查出来的结果用来存到redis当中redis简介->入门 这样下一个请求来的时候就去redis里面了,就减轻了数据库的压力 缓存使用的简单的策略 redis的整合步骤 1. 将redis整

三分钟搞懂 Zookeeper 可以做什么-爱代码爱编程

文章目录 一.什么是zookeeper二.为什么zookeeper 可以干这么多?2.1监听器Zookeeper 是怎么做到的?3.1统一配置管理3.2 统一命名服务3.3 分布式锁3.4集群状态最后 一.什么是zookeeper zookeeper 主要是服务于分布式服务,可以用zookeeper来做:统一配置管理,统一命名服务,分布

Redis知识点总结(操作入门级)-爱代码爱编程

Redis笔记目录 nosql 讲解 nosql 数据模型 Nosql 四大分类 CAP BASE Redis 入门 Redis安装(Window & Linux服务器) 五大基本数据类型 String List Set Hash Zset 三种特殊数据类型 geo hyperloglog bitmap Redi

Flink入门之对checkpoint和Flink内部精确一次性消费的理解-爱代码爱编程

Flink--Checkpoint机制原理 前言一、如何理解flink中state(状态)Ⅰ、state理解Ⅱ、案例理解stateⅢ、为什么需要state管理Ⅳ、理想中的state管理二、如何理解flink中checkpoint(检查点)Ⅰ、执行流程Ⅱ、ck保存了什么Ⅲ、单分区单并行度执行流程详解Ⅳ、多分区多并行度执行流程详解三、如何理解Flink

什么?你还不会Redis?超级详细最新Redis教程-爱代码爱编程

文章目录 NoSQL的特点NoSQL的四大分类Redis入门概述Linux安装测试性能基础知识五大数据类型Redis-KeyString(字符串)List(列表)Set(集合)Hash(哈希)Zset(有序集合)三种特殊数据类型geospatial地理位置HyperloglogBitmaps事务Jedis常用的APISpringBoot整合Redi

三分钟带你入门-redis-高可用架构之哨兵-爱代码爱编程

什么是哨兵? 哨兵(Sentinel)是 redis 的高可用性解决方案,前面我们讲的主从复制它是高可用的基础,但是单纯的主从复制需要人工介入才能完成故障转移,哨兵可以解决这个问题,在主从复制情况下,当主节点发生故障时,哨兵可以自动的发现故障并且完成故障转移,实现真正的 redis 高可用。在哨兵集群中,哨兵会监视所有的 redis 服务器和其他 sen

分布式锁优化过程、Redisson,AOP实现缓存-爱代码爱编程

分布式锁优化过程、Redisson,AOP实现缓存 一 分布式锁优化过程 1 本地锁的局限性 我们学习过synchronized及lock锁,这些锁都是本地锁。接下来写一个案例,演示本地锁的问题 1.1 编写测试代码 在TestController中添加测试方法 public interface RedisTestService { /

hadoop2.2.0伪分布式搭建-爱代码爱编程

1.准备Linux环境 1.1 开启网络,ifconfig指令查看ip 1.2 修改主机名为自己名字(hadoop) vim /etc/sysconfig/network NETWORKING=yes HOSTNAME=hadoop 1.3修改主机名和IP的映射关系 vim /etc/hosts 192.168.182.128 hadoop 1.4关

xxl-job快速入门+详细教程-爱代码爱编程

XXL-Job快速入门+详细教程 1 概念 XXL-JOB是一个轻量级分布式任务调度平台 详细说明:XXL-JOB是一个任务调度框架,通过引入XXL-JOB相关的依赖,按照相关格式撰写代码后,可在其可视化界面进行任务的启动

redis 基本数据类型 持久化,分布式缓存,集群_redis的底层数据基本数据结构,redis缓存,分布式锁,事务,持久化,集群-爱代码爱编程

Redis 内容有点多,但是相信我,绝对干货,发现问题希望可以指出,作者看见就会尽快完善 作为入门到实战,总结的实用教程,如果你发现缺那部分,私聊作者,会尽快补全 有需要私聊作者,发给你markdown 源文档。 应用