10.分布式与微服务

10.1分布式通信

10.1.1 谈谈你对RPC框架的理解

就是远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议,凡是符合该协议的框架,我们都可以称它为 RPC 框架。
关于 RPC 协议,通俗来讲就是,A 计算机提供一个服务,B 计算机可以像调用本地服务那样调用 A 计算机的服务。
要实现 RPC,需要通过网络传输数据,并对调用的过程进行封装。
现在比较流行的 RPC 框架,都会采用 TCP 作为底层传输协议。
RPC 强调的是过程调用,调用的过程对用户而言是透明的,用户不需要关心调用的细节,可以像调用本地服务一样调用远程服务。
一个完整的 RPC 架构里面包含了四个核心的组件
1)客户端(Client),服务的调用方。
2)服务端(Server),真正的服务提供者。
3)客户端存根(Client Stub),存放服务端的地址消息,再将客户端的请求参数打包成网络消息,然后通过网络远程发送给服务方。
4)服务端存根(Server Stub),接收客户端发送过来的消息,将消息解包,并调用本地的方法。
目前比较流行的开源 RPC 框架有 Google 的 gRPC,Facebook 的 Thrift,阿里巴巴的 Dubbo。
在分布式架构中,原本的单体应用被拆分成多个独立部署的服务分布在计算机网络上,这些服务必然需要通过网络进行数据交互。
而 RPC 框架就是解决在分布式架构中的各个业务服务彼此的网络通信问题。
一般来说,RPC 服务主要是针对大型的企业,也就说当我们业务复杂度以及用户量都比较高时,需要解耦服务,扩展性强、部署灵活
一般市面上开源的 PRC 框架,除了提供基础的远程通信功能以外,还会在性能消耗、传输效率、服务治理等方面做很多的设计

10.1.2 Http和Rpc框架的区别

RPC ,它是一种针对跨进程或者跨网络节点的应用之间的远程过程调用协议。
它的核心目标是,让开发人员在进行远程方法调用的时候,就像调用本地方法一样,不需要额外为了完成这个交互做过的编码。
为了达到这样一个目标 Client stub 作为客户端存根,代理客户端请求并把请求参数进行组装,再把组装的参数通过 Pack 也就是序列化。
最后通过远程通信协议把序列化的数据传输到目标服务器上。
服务端收到数据以后,通过 Unpack 也就是反序列化,再通过 Server stub 服务端存根来调用目标方法获取执行结果。
让开发者在没有任何感知的情况下实现了远程方法的调用。
而 Http 协议是为 Web 浏览器与 Web 服务器之间的通信而设计的远程通信协议,它定义了通信协议的报文规范(如图),我们可以使用 http 协议来实现跨网络节点的数据传输。

10.2 微服务协调组件

10.2.1 分布式和微服务的区别是什么

分布式是一组通过网络进行通信,并且为了完成共同的计算任务的计算机节点组成的系统
在集中式系统里面,要想提升程序的运行性能, 把原本的单体应用进行拆分,部署到多个计算机节点上,然后各个服务之间使用RPC进行通信。
针对这种分布式部署的应用架构,我们称为 SOA(面向服务)的架构。
其次,我再解释一下微服务架构。
其实微服务架构本身就是一种分布式架构,它强调的是对部署在各个计算机上的应用服务的粒度。
它的核心思想是,针对拆分的服务节点做更进一步的解耦。
也就是说,针对 SOA 服务化架构下的单个业务服务,以更加细粒度的方式进一步拆分。
每个拆分出来的微服务由独立的小团队负责,最好在 3 人左右。

10.2.2 谈谈你对负载均衡的理解

负载均衡是作用在网络通信上,来实现请求的分发。
Ribbon 是 一个客户端负载均衡器,主要用于在微服务架构中实现客户端负载均衡。它可以在多个服务实例之间分发请求,从而提高系统的性能和可靠性。Ribbon 通常与 Eureka 服务注册与发现组件一起使用,但它也可以与其他服务发现机制集成。
Ribbon 的主要功能和特点

  1. 客户端负载均衡:
    ○ Ribbon 实现了客户端负载均衡,这意味着负载均衡逻辑在客户端执行。客户端根据负载均衡策略选择一个服务实例进行请求,而不是通过中央负载均衡器。
  2. 多种负载均衡策略:
    ○ Ribbon 提供了多种负载均衡策略,例如轮询(Round Robin)、随机(Random)、加权响应时间(Weighted Response Time)等。开发者可以根据需求选择合适的策略,甚至可以自定义策略。
  3. 与 Eureka 集成:
    ○ Ribbon 可以与 Eureka 集成,自动从 Eureka 注册表中获取可用的服务实例列表,并根据负载均衡策略进行请求分发。这种集成简化了服务发现和负载均衡的配置和管理。
  4. 故障和重试机制:
    ○ Ribbon 提供了故障和重试机制,当选定的服务实例不可用时,Ribbon 可以自动重试其他实例。这种机制提高了系统的容错性和可靠性。
  5. 配置灵活:
    ○ Ribbon 的配置非常灵活,可以通过配置文件或代码进行定制。开发者可以配置超时、重试次数、负载均衡策略等参数。
    Ribbon 的工作原理
  6. 获取服务实例列表:
    ○ 当 Ribbon 与 Eureka 集成时,Ribbon 客户端会从 Eureka 注册表中获取指定服务的所有可用实例列表。
  7. 选择负载均衡策略:
    ○ Ribbon 根据配置的负载均衡策略,从服务实例列表中选择一个实例进行请求。例如,如果使用轮询策略,Ribbon 会按顺序选择实例;如果使用随机策略,Ribbon 会随机选择一个实例。
  8. 发送请求:
    ○ Ribbon 客户端将请求发送到选定的服务实例。如果请求失败,Ribbon 可以根据配置进行重试,选择其他实例进行请求。
    总结
    Ribbon 是一种强大的客户端负载均衡器,特别适合微服务架构。它提供了多种负载均衡策略、故障和重试机制,并且可以与 Eureka 等服务发现组件无缝集成。通过使用 Ribbon可以轻松实现客户端负载均衡,提高系统的性能和可靠性。

10.2.3 谈谈你对ZooKeeper的理解

ZooKeeper 是一个开放源码的分布式协调服务 , 它是集群的管理者 , 监视着集群中各个 节点的状态根据节点提交的反馈进行下一步合理操作。最终 ,将简单易用的接口和性能高效、功能稳定的系统提供给用户。
分布式应用程序可以基于 Zookeeper 实现诸如数据发布/订阅、负载均衡、命名服务、分 布式协调/通知、集群管理、 Master 选举、分布式锁和分布式队列等功能。

10.2.4 简述Zookeeper中的Watch机制的原理

Zookeeper 是一个分布式协调组件,为分布式架构下的多个应用组件提供了顺序访问控制能力。

它的数据存储采用了类似于文件系统的树形结构,以节点的方式来管理存储在 Zookeeper 上的数据。
Watch 机制,可以让客户端感知到 Zookeeper Server 上存储的数据变化,这样一种机制可以让 Zookeeper 实现很多的场景,比如配置中心、注册中心等。
Watch 机制采用了 Push 的方式来实现,也就是说客户端和 Zookeeper Server 会建立一个长连接,
一旦监听的指定节点发生了变化,就会通过这个长连接把变化的事件推送给客户端。
(如图) Watch 的具体流程分为几个部分:
 首先,是客户端通过指定命令比如 exists、get,对特定路径增加 watch
 然后服务端收到请求以后,用 HashMap 保存这个客户端会话以及对应关注的节点路径,同时客户端也会使用 HashMap存储指定节点和事件回调函数的对应关系。
 当服务端指定被 watch 的节点发生变化后,就会找到这个节点对应的会话,把变化的事件和节点信息发给这个客户端。
 客户端收到请求以后,从 ZkWatcherManager 里面对应的回调方法进行调用,完成事件变更的通知。
在这里插入图片描述

10.2.5 Zookeeper如何实现Leader选举

首先,Zookeeper 集群节点由三种角色组成,分别是
 Leader,负责所有事务请求的处理,以及过半提交的投票发起和决策。
 Follower,负责接收客户端的非事务请求,而事务请求会转发给 Leader 节点来处理,另外,Follower 节点还会参与 Leader 选举的投票。
 Observer,负责接收客户端的非事务请求,事务请求会转发给 Leader 节点来处理,另外 Observer 节点不参与任何投票,只是为了扩展 Zookeeper 集群来分担读操作的压力。
其次,Zookeeper 集群是一种典型的中心化架构,也就是会有一个 Leader 作为决策节点,专门负责事务请求的处理和数据的同步。
这种架构的好处是可以减少集群架构里面数据同步的复杂度,集群管理会更加简单和稳定。
但是,会带来 Leader 选举的一个问题,也就是说, 如果 Leader 节点宕机了,为了保证集群继续提供可靠的服务,Zookeeper 需要从剩下的 Follower 节点里面去选举一个新的节点作为 Leader 。
具体的实现是,
每一个节点都会向集群里面的其他节点发送一个票据 Vote,这个票据包括三个属性。
 epoch, 逻辑时钟,用来表示当前票据是否过期。
 zxid,事务 id,表示当前节点最新存储的数据的事务编号
 myid,服务器 id,在 myid 文件里面填写的数字。
每个节点都会选自己当 Leader,所以第一次投票的时候携带的是当前节点的信息。
接下来每个节点用收到的票据和自己节点的票据做比较,根据 epoch、zxid、myid 的顺序逐一比较,
以值最大的一方获胜。比较结束以后这个节点下次再投票的时候,发送的投票请求就是获胜的 Vote 信息。
然后通过多轮投票以后,每个节点都会去统计当前达成一致的票据,以少数服从多数的方式,最终获得票据最多的节点成为 Leader

10.3 分布式锁

10.3.1 谈谈你对分布式锁的理解和实现

使用分布式锁的目的,是为了保证同一时间只有一个 JVM 进程可以对共享资源进行操作。
根据锁的用途可以细分为以下两类:
 允许多个客户端操作共享资源,我们称为共享锁
这种锁的一般是对共享资源具有幂等性操作的场景,主要是为了避免重复操作共享资源频繁加锁带来的性能开销。
 只允许一个客户端操作共享资源,我们称为排他锁
这种锁一般是用在对共享资源操作具有非幂等性操作的场景,也就是需要保证在同一时刻只有一个进程或者线程能够访问这个共享资源。

10.3.2 什么是幂等,如何解决幂等性问题

幂等是指一个方法被多次重复执行的时候产生的影响和第一次执行的影响相同。
之所以要考虑到幂等性问题,是因为在网络通信中,存在两种行为可能会导致接口被重复执行。

  1. 用户的重复提交或者用户的恶意攻击,导致这个请求会被多次重复执行。
  2. 在分布式架构中,为了避免网络通信导致的数据丢失,在服务之间进行通信的时候都会设计超时重试的机制,而这种机制有可能导致服务端接口被重复调用。
    所以在程序设计中,对于数据变更类操作的接口,需要保证接口的幂等性。
    而幂等性的核心思想,其实就是保证这个接口的执行结果只影响一次,后续即便再次调用,也不能对数据产生影响,所以基于这样一个诉求,常见的解决方法有很多。
  3. 使用数据库的唯一约束实现幂等,比如对于数据插入类的场景,比如创建订单,因为订单号肯定是唯一的,所以如果是多次调用就会触发数据库的唯一约束异常,从而避免一个请求创建多个订单的问题。
  4. 使用 redis 里面提供的 setNX 指令,比如对于 MQ 消费的场景,为了避免 MQ 重复消费导致数据多次被修改的问题,可以在接收到 MQ 的消息时,把这个消息通过 setNx 写入到 redis 里面,一旦这个消息被消费过,就不会再次消费。
  5. 使用状态机来实现幂等,所谓的状态机是指一条数据的完整运行状态的转换流程,比如订单状态,因为它的状态只会向前变更,所以多次修改同一条数据的时候,一旦状态发生变更,那么对这条数据修改造成的影响只会发生一次。
    当然,除了这些方法以外,还可以基于 token 机制、去重表等方法来实现,但是不管是什么方法,无非就是两种,
     要么就是接口只允许调用一次,比如唯一约束、基于 redis 的锁机制。
     要么就是对数据的影响只会触发一次,比如幂等性、乐观锁

10.3.3 谈谈你对一致性hsah算法的理解

10.3.4 常用的分布式ID设计方案有哪些

首先,分布式全局 ID 的解决方案有很多,比如:
 使用 Mysql 的全局表
 使用 Zookeeper 的有序节点
 使用 MongoDB 的 objectid
 redis 的自增 id
 UUID 等等
 …… 这些方案只是解决基础的 id 唯一性问题,在实际生产环境中,需要构建一个全局唯一 id
还需要考虑更多的因素:
 有序性, 有序的 ID 能够更好地确认数据的位置,以及 B+数据的存储结构中,范围查询的效率更高,并且可以提升 B+树数据维护的效率。
 安全性,避免恶意爬取数据造成数据泄露
 可用性,ID 生成系统的可用性要求非常高,一旦出现故障就会造成业务不可用的问题
 性能,全局 id 生成系统需要满足整个公司的业务需求,涉及亿级别的调用,对性能要求较高
因此,如果我们选择数据库的全局表,你每获取一次 id 就需要更新数据库,性能上限比较明显,而且基于数据库构建高扩展和高性能的解决方案难度很大。
所以,目前市面上主流的解决方案是基于 Twitter 早期开源的 Snowflake 雪花算法。
它是由 64 位长度组成的全局 id 生成算法,通过对 64 位进行区间划分来表述不同含义实现唯一性。
它的好处是:
 算法实现简单
 不存在太多外部依赖
 可以生成有意义的有序编号
 基于位运算,性能也很好,Twitter 测试的峰值是 10 万个每秒。
另外,美团公司开源了一个全局唯一 id 生成系统 leaf,它里面也用到了雪花算法去构建全局唯一 id
并且在高性能和高可用方面,做了很多的优化,为美团内部业务提供了每天上亿次的调用。

10.3.5 实现分布式锁,Zookeeper和Redis哪个更好

目前实现分布式锁最常用的中间件是 Redis 和 Zookeeper
第一种,Redis 可以通过两种方式来实现

  1. 利用 Redis 提供的`SET key value NX PX milliseconds`指令,这个指令是设置一个 key-value,如果 key 已经存在,则返回 0,否则返 回 1,我们基于这个返回值来判断锁的占用情况从而实现分布式锁
  2. 基于 Redission 客户端来实现分布式锁,Redisson 提供了分布式锁的封装方法,我们只需要调用api 中的`lock()`和`unlock()`方法。它帮我们封装锁实现的细节和复杂度
     redisson 所有指令都通过 lua 脚本执行并支持 lua 脚本原子性执行
     redisson 中有一个 watchdog 的概念,翻译过来就是看门狗,它会在你获取锁之后,每隔 10 秒帮你把 key 的超时时间设为 30s,就算一直持有锁也不会出现 key 过期了。“看门狗”的逻辑保证了没有死锁发生。
    第二种,基于 ZK 实现分布式锁的落地方案
    Zookeeper 实现分布式锁的方法比较多,我们可以使用有序节点来实现,
    在这里插入图片描述
    两种方案都有各自的优缺点
    对于 redis 的分布式锁而言,它有以下缺点:
     它获取锁的方式简单粗暴,如果获取不到锁,会不断尝试获取锁,比较消耗性能。
     Redis 是 AP 模型,在集群模式中由于数据的一致性会导致锁出现问题,即便使用 Redlock 算法来实现,在某些复杂场景下,也无法保证其实现100%的可靠性。
    不过在实际开发中使用 Redis 实现分布式锁还是比较常见,而且大部分情况下不会遇到极端复杂的场景,更重要的是 Redis 性能很高,在高并发场景中比较合适。
    对于 zk 分布式锁而言:
     zookeeper 天生设计定位就是分布式协调,强一致性。锁的模型健壮、简单易用、适合做分布式锁。
     如果获取不到锁,只需要添加一个监听器就可以了,不用一直轮询,性能消耗较小。
    如果要在两者之间做选择,就我个人而言的话,比较推崇 ZK 实现的锁,因为对于分布式锁而言,它应该符合 CP 模型,但是 Redis 是 AP 模型,所以在这个点上,Zookeeper 会更加合适

10.4 分布式事务

10.4.1 如何区分Spring中的事务和分布式事务

, 在 Spring 里面并没有提供事务,它只是提供了对数据库事务管理的封装。
通过声明式的事务配置,使得开发人员可以从一些复杂的事务处理中得到解脱,
我们不再需要关心连接的获取、连接的关闭、事务提交、事务回滚这些操作。
更加聚焦在业务开发层面。
所以,Spring 里面的事务,本质上就是数据库层面的事务,
这种事务的管理,主要是针对单个数据库里面多个数据表操作的,去满足事务的 ACID 特性。
分布式事务,是解决多个数据库的事务操作的数据一致性问题,传统的关系型数据库不支持跨库事务的操作,所以需要引入分布式事务的解决方案。
Spring 并没有提供分布式事务场景的支持, 我们可以使用一些主流的事务解决框架,比如 Seata,集成到 Spring 生态里面,去解决分布式事务的问题。

10.4.2 谈谈分布式事务的解决方案

分布式事务是指存在多个跨库事务的事务一致性问题,
或者是指在分布式架构下由多个应用节点组成的多个事务之间的事务一致性问题。
目前主流的分布式事务解决方案有两种
 一种是基于 XA 协议实现的强一致性事务方案,比如 Atomikos、Seata 中的XA 事务模型。
基于 CAP 理论可以知道,如果要保证分布式事务的强一致性,就必然会带来性能的影响从而影响到可用性。
所以强一致性事务性能会比较低。
 另一种是基于 BASE 理论下的弱一致性事务解决方案,比如 TCC 事务模型、基于可靠性消息的最终一致性方案、Seata 的 Saga 事务模型等。
最终一致性事务损失了数据的强一致性,通过异步补偿的方式达到数据的最终一致。
因此在性能上比较好,适用于并发量比较高的场景。
分布式事务的原理
分布式事务是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于分布式系统的不同节点之上。
比如大型的电商系统中的下单场景,会涉及扣库存、优惠促销计算、订单 ID 生成。通常情况下,库存、促销、主键生成策略都位于不同的服务器和数据库表中。
下单接口的成功与否,不仅取决于本地节点的数据库操作,而且还依赖第三方系统的结果,这时候分布式事务就保证这些操作要么全部成功,要么全部失败。
因此,本质上来说,分布式事务就是为了保证不同数据库的数据一致性。
基于 CAP 定理可以知道,对于上述情况产生的分布式事务问题,我们要么采用强一致性方案、要么采用弱一致性方案。
 所谓强一致性,就是指通过第三方的事务管理器来协调多个节点的事务,保证每个节点的事务达到
同时成功和同时失败,为了实现这样一个需求,我们会引入 Xopen/DTP 模型提供的 XA 协议,基于 2pc 或者 3pc 的方式来实现。但是,在如果全局事务管理器中的多个节点中,如果任意一个节点在进行事务提交确认时,由于网络通信延迟导致阻塞,就会影响到所有节点事务的提交,而这个阻塞过程也会影响阻塞用户的请求线程,这对于用户体验以及整体性能的影响较大。
 而弱一致性方案,就是针对强一致性方案所衍生出来性能和数据一致性平衡的一个方案,简单来说就是损失掉强一致性,数据在某一个时刻会存在不一致的状态,但是最终这些数据会达成一致。这样的好处是提升了系统的性能。
在弱一致性方案中,常见的解决方案:

  1. 使用分布式消息队列,来实现最终一致性
  2. 基于 TCC 事务,通过演进版本的二阶段提交实现最终一致性
  3. 使用 Seata 事务框架,它提供了多种事务模式,如 AT、XA、Saga、TCC 等

10.4.3 谈谈你对Seata的理解

  1. 在微服务架构下,由于数据库和应用服务的拆分,导致原本一个事务单元中的多个 DML 操作,
    变成了跨进程或者跨数据库的多个事务单元的多个 DML 操作,
    而传统的数据库事务无法解决这类的问题,所以就引出了分布式事务的概念。
  2. 分布式事务本质上要解决的就是跨网络节点的多个事务的数据一致性问题,业内常见的解决方法有两种
    a. 强一致性,就是所有的事务参与者要么全部成功,要么全部失败,全局事务协调者需要知道每个事务参与者的执行状态,再根据状态来决定数据的提交或者回滚!
    b. 最终一致性,也叫弱一致性,也就是多个网络节点的数据允许出现不一致的情况,但是在最终的某个时间点会达成数据一致。
    基于 CAP 定理我们可以知道,强一致性方案对于应用的性能和可用性会有影响,所以对于数据一致性要求不高的场景,就会采用最终一致性算法。
  3. 在分布式事务的实现上,对于强一致性,我们可以通过基于 XA 协议下的二阶段提交来实现,对于弱一致性,可以基于 TCC 事务模型、可靠性消息模型等方案来实现。
  4. 市面上有很多针对这些理论模型实现的分布式事务框架,我们可以在应用中集成这些框架来实现分布式事务。
    而 Seata 就是其中一种,它是阿里开源的分布式事务解决方案,提供了高性能且简单易用的分布式事务服务。
    Seata 中封装了四种分布式事务模式,分别是:
     AT 模式,是一种基于本地事务+二阶段协议来实现的最终数据一致性方案,也是 Seata 默认的解决方案
    在这里插入图片描述
    TCC 模式,TCC 事务是 Try、Confirm、Cancel 三个词语的缩写,简单理解就是把一个完整的业务逻辑拆分成三个阶段,然后通过事务管理器在业务逻辑层面根据每个分支事务的执行情况分别调用该业务的 Confirm 或者 Cacel 方法。
    Saga 模式,Saga 模式是 SEATA 提供的长事务解决方案,在 Saga 模式中,业务流程中每个参与者都提交本地事务,当出现某一个参与者失败则补偿前面已经成功的参与者。
    XA 模式,XA 可以认为是一种强一致性的事务解决方法,它利用事务资源(数据库、消息服务等)对 XA 协议的支持,以 XA 协议的机制来管理分支事务的一种 事务模式。
    在不同的业务场景中,我们可以使用 Seata 的不同事务模型来解决不同业
    务场景中的分布式事务问题,因此我们可以认为 Seata 是一个一站式的分布式事务解决方案。

10.4.4 如何解决TCC的悬挂问题

所谓 TCC,其实就是(Try-Confirm-Cancel),也就是把一个事务拆分成两个阶段,类似于传统的 XA事务模型。
Try 这个阶段,是实现业务的检查,预留必要的业务资源。
Confirm,真正执行业务逻辑,只需要使用 try 阶段预留的业务资源进行处理就行。
Cancel,如果事务执行失败,就通过 cancel 方法释放 try 阶段预留的资源。
在 TCC 事务模式下,我们通过一个事务协调器来管理多个事务,每个事务先执行 try 方法。
当所有事务参与者的 try 方法执行成功,就执行 confirm 方法完成真正逻辑的执行,一旦任意一个事务参与者出现异常,就通过 cancel 接口触发事务回滚,释放 Try 阶段占用的资源。
在这里插入图片描述
很显然,这是一个最终一致性的实现方案,因此当 Try 执行成功,就必须确保Confirm 执行成功。
当 Try 执行失败,就必须确保 Cancel 实现资源释放。
而 悬挂问题,指的是 TCC 执行 Try 接口出现网络超时时候,使得 TCC 触发 Cancel 接口回滚,
但可能在回滚之后,这个超时的 Try 接口才被真正执行,也就导致 Cancel 接口比 Try 接口先执行。
从而造成 Try 接口预留的资源一直无法释放,这种情况就是悬挂。
因为有可能会造成比较严重的生产事故。
了解了背景之后,我们应该如何解决呢。
对于悬挂问题,我认为只需要保证 Cancel 接口执行完以后,Try 接口不允许再执行就可以了。
所以,我们可以在 Try 接口里面,先判断 Cancel 接口有没有执行过,如果已经执行过,就不再执行。
是否执行过的这个判断,可以在事务控制表里面插入一条事务控制记录来标记这个事务的回滚状态。
然后在 Try 接口中只需要读取这个状态来判断就行了。

10.5 谈谈你对Swagger的工作流程的理解

Swagger 广泛用于可视化 API ,使用 Swagger UI 为前端开发人员提供在线沙箱。
Swagger 是用于生成 RESTful Web 服务的可视化表示的工具,规范和完整框架实现。 它 使文档能够以与服务器相同的速度更新。 当通过 Swagger 正确定义时,消费者可以使用最 少量的实现逻辑来理解远程服务并与其进行交互。 因此,Swagger 消除了调用服务时的猜测。

10.6雪花算法的实现原理

雪花算法是一种生成分布式全局唯一 ID 的算法,它会得到一个 64 位长度的long 类型数据。
其中这 64 位的数据,由 4 个部分组成
 第一个 bit 位是符号位,因为 id 不会是负数,所以它一般是 0
 接着用 41 个 bit 位来表示毫秒单位的时间戳
 再用 10 个 bit 位来表示工作机器 id
 最后 12 个 bit 位表示递增的序列号
把这 64 个 bit 位拼接成一个 long 类型的数字,就是雪花算法的实现。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值