snowflake

面试刷题31:分布式ID设计方案

旧时模样 提交于 2020-04-07 07:38:13
面试中关于分布式的问题很多。(分布式事务,基本理论CAP,BASE,分布式锁)先来一个简单的。 简单说一下分布式ID的设计方案? 首先要明确在分布式环境下,分布式id的基本要求。 1, 全局唯一,在分布式集群下,不同的节点并发生成的分布式id要唯一; 2, 顺序性,分布式id是有序生成 然后给出分布式id的设计方案。 1, 基于数据的自增id生成分布式ID,使用比较简单,缺点是扩展性和可靠性有限; 基于数据库表的自增id 2,基于 snowflake 算法生成; snowflake生成的分布式id是一个64位整数;位数标识如下: 1 标识正负 41位,一般使用System.currentTimeMilles()得到; 5 数据中心标识 5 机器ip标识 12 单位毫秒内可以生成的序数极限 snowflake的生成跟时间相关的使用的是System.currentTimeMilles(),跟冬令时没有关系。 分布式id的进一步要求 可靠性: 即高可用 紧凑性: 64位的整数比较长,不太紧凑,作为索引,存储不占优势。 有意义: 可以放入业务标识或者时间 snowflake的缺点 受时间影响:需要保证分布式集群的时间同步,即NTP ; 可以预测到:容易按照时间规律预测到,进而影响安全性; 小结 回答了分布式id的基本要求,已经常用方案。 原创不易,点赞关注支持一下吧!转载请注明出处

开源分布式ID生成器UidGenerator的技术实现

可紊 提交于 2020-04-06 19:17:16
1、引言 很多人一想到IM应用开发,第一印象就是“长连接”、“socket”、“保活”、“协议”这些关键词,没错,这些确实是IM开发中肯定会涉及的技术范畴。 但,当你真正开始编写第一行代码时,最现实的问题实际上是“聊天消息ID该怎么生成?”这个看似微不足道的小事情。说它看似微不足道,是因为在IM里它太平常了,处处可见它的身影。不过,虽然看似微不足道,但实际却很重要,因为它的生成算法和生成策略的优劣在某种意义上来说,决定了你的IM应用层某些功能实现的难易度。 有签于此,即时通讯网专门整理了“IM消息ID技术专题”系列文章,希望能带给你对这个看似微小但却很重要的技术点有更深刻的理解和最佳实践思路。 本文是专题系列文章的第5篇,专门介绍百度开源的分布式消息ID生成器UidGenerator的算法逻辑、实现思路、重点源码解读等,或许能带给你更多的启发。 2、基本介绍 全局ID(常见的比如:IM聊天系统中的消息ID、电商系统中的订单号、外卖应用中的订单号等)服务是分布式服务中的基础服务,需要保持全局唯一、高效、高可靠性。有些时候还可能要求保持单调,但也并非一定要严格递增或者递减。 全局ID也可以通过数据库的自增主键来获取,但是如果要求QPS很高显然是不现实的。 UidGenerator ( 备用地址 )工程是百度开源的基于Snowflake算法的唯一ID生成器

使用带粒子效果的 CAEmitterLayer

余生长醉 提交于 2020-03-26 07:30:37
1. 用 CAEmitterLayer 产生粒子效果 2. 封装 CAEmitterLayer 3. 封装下雪、下雨的粒子效果控件 一、用 CAEmitterLayer 产生粒子效果 - ( void )emitterLayer { // 1. 创建出 Layer CAEmitterLayer *emitterLayer = [CAEmitterLayer layer]; // 显示边框 emitterLayer.borderWidth = 1.f ; // 给定尺寸 emitterLayer.frame = CGRectMake( 100 , 100 , 100 , 100 ); //emitterLayer.mask = YES; 不超过范围 // 发射点 emitterLayer.emitterPosition = CGPointMake( 0 , 0 ); // 发射模式 emitterLayer.emitterMode =kCAEmitterLayerSurface; // 发射形状 emitterLayer.emitterShape =kCAEmitterLayerLine; // 加入 layer [ self .view.layeraddSublayer:emitterLayer]; // 2. 创建粒子 CAEmitterCell *cell =

开源分布式ID生成器UidGenerator的技术实现

て烟熏妆下的殇ゞ 提交于 2020-03-19 18:20:18
3 月,跳不动了?>>> 1、引言 很多人一想到IM应用开发,第一印象就是“长连接”、“socket”、“保活”、“协议”这些关键词,没错,这些确实是IM开发中肯定会涉及的技术范畴。 但,当你真正开始编写第一行代码时,最现实的问题实际上是“聊天消息ID该怎么生成?”这个看似微不足道的小事情。说它看似微不足道,是因为在IM里它太平常了,处处可见它的身影。不过,虽然看似微不足道,但实际却很重要,因为它的生成算法和生成策略的优劣在某种意义上来说,决定了你的IM应用层某些功能实现的难易度。 有签于此,即时通讯网专门整理了“IM消息ID技术专题”系列文章,希望能带给你对这个看似微小但却很重要的技术点有更深刻的理解和最佳实践思路。 本文是专题系列文章的第5篇,专门介绍百度开源的分布式消息ID生成器UidGenerator的算法逻辑、实现思路、重点源码解读等,或许能带给你更多的启发。 2、基本介绍 全局ID(常见的比如:IM聊天系统中的消息ID、电商系统中的订单号、外卖应用中的订单号等)服务是分布式服务中的基础服务,需要保持全局唯一、高效、高可靠性。有些时候还可能要求保持单调,但也并非一定要严格递增或者递减。 全局ID也可以通过数据库的自增主键来获取,但是如果要求QPS很高显然是不现实的。 UidGenerator ( 备用地址 )工程是百度开源的基于Snowflake算法的唯一ID生成器

理解分布式id生成算法SnowFlake

生来就可爱ヽ(ⅴ<●) 提交于 2020-03-12 22:42:09
分布式id生成算法的有很多种,Twitter的SnowFlake就是其中经典的一种。 概述 SnowFlake算法生成id的结果是一个64bit大小的整数,它的结构如下图: 1位 ,不用。二进制中最高位为1的都是负数,但是我们生成的id一般都使用整数,所以这个最高位固定是0 41位 ,用来记录时间戳(毫秒)。 41位可以表示个数字, 如果只用来表示正整数(计算机中正数包含0),可以表示的数值范围是:0 至 ,减1是因为可表示的数值范围是从0开始算的,而不是1。 也就是说41位可以表示个毫秒的值,转化成单位年则是年 10位 ,用来记录工作机器id。 可以部署在个节点,包括 5位datacenterId 和 5位workerId 5位(bit) 可以表示的最大正整数是,即可以用0、1、2、3、....31这32个数字,来表示不同的datecenterId或workerId 12位 ,序列号,用来记录同毫秒内产生的不同id。 12位(bit) 可以表示的最大正整数是,即可以用0、1、2、3、....4094这4095个数字,来表示同一机器同一时间截(毫秒)内产生的4095个ID序号 由于在Java中64bit的整数是long类型,所以在Java中SnowFlake算法生成的id就是long来存储的。 SnowFlake可以保证: 所有生成的id按时间趋势递增

MySQL分库分表环境下全局ID生成方案

百般思念 提交于 2020-03-02 18:41:32
在大型互联网应用中,随着用户数的增加,为了提高应用的性能,我们经常需要对数据库进行分库分表操作。在单表时代,我们可以完全依赖于数据库的自增ID来唯一标识一个用户或数据对象。但是当我们对数据库进行了分库分表后,就不能依赖于每个表的自增ID来全局唯一标识这些数据了。因此,我们需要提供一个全局唯一的ID号生成策略来支持分库分表的环境。下面来介绍两种非常优秀的解决方案: ###1. 数据库自增ID——来自Flicker的解决方案 因为MySQL本身支持auto_increment操作,很自然地,我们会想到借助这个特性来实现这个功能。Flicker在解决全局ID生成方案里就采用了MySQL自增长ID的机制(auto_increment + replace into + MyISAM)。一个生成64位ID方案具体就是这样的: 先创建单独的数据库(eg:ticket),然后创建一个表: CREATE TABLE Tickets64 ( id bigint(20) unsigned NOT NULL auto_increment, stub char(1) NOT NULL default '', PRIMARY KEY (id), UNIQUE KEY stub (stub) ) ENGINE=MyISAM 当我们插入记录后,执行 SELECT * from Tickets64

面试官:分库分表之后,id 主键如何处理?

蹲街弑〆低调 提交于 2020-02-29 19:49:58
面试题 分库分表之后,id 主键如何处理? 面试官心理分析 其实这是 分库分表之后你必 然要面对的一个问题,就是 id 咋生成?因为要是分成多个表之后,每个表都是从 1 开始累加,那肯定不对啊,需要一个全局唯一的 id 来支持。所以这都是你实际生产环境中必须考虑的问题。 面试题剖析 数据库自增 id 这个就是说你的系统里每次得到一个 id,都是往一个库的一个表里插入一条没什么业务含义的数据,然后获取一个数据库自增的一个 id。拿到这个 id 之后再往对应的分库分表里去写入。 这个方案的好处就是方便简单,谁都会用;缺点就是单库生成自增 id,要是高并发的话,就会有瓶颈的;如果你硬是要改进一下,那么就专门开一个服务出来,这个服务每次就拿到当前 id 最大值,然后自己递增几个 id,一次性返回一批 id,然后再把当前最大 id 值修改成递增几个 id 之后的一个值;但是无论如何都是基于单个数据库。 适合的场景:你分库分表就俩原因,要不就是单库并发太高,要不就是单库数据量太大;除非是你并发不高,但是数据量太大导致的分库分表扩容,你可以用这个方案,因为可能每秒最高并发最多就几百,那么就走单独的一个库和表生成自增主键即可。 UUID 好处就是本地生成,不要基于数据库来了;不好之处就是,UUID 太长了,作为主键性能太差了,另外 UUID 不具有有序性,会造成 B+

Twitter的分布式自增ID算法snowflake(Java版)

自古美人都是妖i 提交于 2020-02-28 15:58:56
/** * Twitter_Snowflake<br> * SnowFlake的结构如下(每部分用-分开):<br> * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 <br> * 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0<br> * 41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截) * 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。41位的时间截,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69<br> * 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId<br> * 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号<br> * 加起来刚好64位,为一个Long型。<br> * SnowFlake的优点是,整体上按照时间自增排序

Twitter-Snowflake 64位自增ID简介

穿精又带淫゛_ 提交于 2020-02-28 15:51:11
在系统中,我们需要为每个资源设置一个唯一ID,单表时代,使用数据库的自增ID可以很简单的达到我们的目的,但是在分布式系统、多库多表的情况下,数据库自增ID就不灵了,因此,我们需要另一种算法来实现分布式环境下的唯一ID。 Snowflake核心算法: 把时间戳、工作id和序列号拼装起来,生成一个64bit的唯一id,符号位不用,其他三组bit可以根据业务需要来进行调整,默认方案下,能使用69年,部署1023台机器,每毫秒能产生4095个自增ID。 这里的69年,1023台机器,4095个自增ID是怎么算出来的的? 假设41个bit都是1,那么转换成10进制就是 2**41-1 = 2199023255552毫秒≈69年,机器数量、自增ID数量也是如此计算。 生成唯一ID的方式很多,为什么是Snowflake? 1、相对有序,数据库插入性能好。 2、Long 型存储,相对于guid uuid占用空间小。 JAVA 实现: public final class Snowflake { private static final Long workerIdBits = 10L; private static final Long maxWorkerId = -1L ^ (-1L << workerIdBits); private static final Long sequenceBits