分布式全局唯一ID (分布式全局唯一id实现方案)

教程大全 2025-07-17 20:34:16 浏览

如何去优化我们公司中已经存在的分布式中的唯一ID,而提起唯一的ID,相信如果不是从事传统行业的人,肯定都有所了解,分布式架构下,唯一ID生成方案,是我们在设计一个系统,尤其是数据库使用分库分表的时候常常会遇见的问题,尤其是当我们进行了分库分表之后,对这个唯一ID的要求也就越来越高。那么唯一ID方案都有哪些呢?

往往一谈分布式,总是会 色变,因为在很多面试的时候,都会问你,会不会分布式?你们项目的架构是怎么做的,做的如何?你们既然使用了分布式,那么你们的分布式事务是怎么处理的,你们分布式全局唯一 ID 使用的是什么算法来实现的?

往往谈到这个的时候,很多面试的朋友就会很尴尬,我都是直接用的,我好像完全没有注意过。当你意识到这一点的时候,往往接下来的问题,你回答的就会开始磕磕绊绊,于是面试凉了。

并发越大的系统,数据就越大,数据越大就越需要分布式,而大量的分布式数据就越需要唯一标识来识别它们,而这些唯一标识,我们就称之为分布式全局唯一的ID。

阿粉的项目说实话,还不是特别的差劲。于是阿粉就开始想着,这分布式的全局唯一ID,为啥生成的时候都是使用 UUID ,要么就是自增主键呢?

于是阿粉准备使用 Redis 来生成分布式全局唯一ID。

因为 Redis 的所有命令是单线程的,所以可以利用 Redis 的原子操作 INCR 和 INCRBY,来生成全局唯一的ID。方式一:StringRedisTemplate

publicclassActivity{privateLongid;privateStringname;privateBigDecimalprice;}

上面是我们的活动的实体类,马上就要 618 了,各位做电商的是不是开始准备搞事情了?可以学习一下用一下试试,我们活动中有 id ,活动的名称 name ,还有对应活动设置好的价格 price 等等,字段可能还会有很多,我们需要的暂时就列出这么多。

publicclassIdGeneratorService{@AutowiredprivateStringRedisTemplatestringRedisTemplate;privatestaticfinalStringID_KEY=;publicLong(){stringRedisTemplate.opsForValue().increment(ID_KEY);}longid=idGeneratorService.incrementId();调用生成

但是看起来是不是总是感觉好像有点 low ,我们是不是就要准备来整的高大上一点,毕竟代码就像一个程序员的内裤,虽然自己看着有洞感觉没啥,但是别人看到是不是就很不爽了,那就整个他们看起来比较高大上一点的。

为什么会有方案二,那是因为我们的 Redis 很多时候都不是只有一个 Redis,都是搭建的集群,既然是集群,我们就要开始合理的利用上集群。

那么我们就要开始考虑到集群方面的知识了,那么我们的思路就有了。于是出现了:集群中每个节点预生成生成ID;然后与redis的已经存在的ID做比较。如果大于,则取节点生成的ID;小于的话,取Redis中最大ID自增。

这个时候我们还需要一段 lua 脚本来保证我们实现的ID是唯一的,这才是真正的本质,不然我们实现的ID在高端,不唯一,有个锤子用

核心脚本:

get_max_seq()key=tostring(KEYS[1])incr_amoutt=tonumber(KEYS[2])seq=tostring(KEYS[3])month_in_seconds=24*60*60*30(1==redis.call(\,key,seq))redis.call(\,key,month_in_seconds)seqprev_seq=redis.call(\,key)(prev_seqthenredis.call(\,key,seq)seq--[[不能直接返回redis.call(\,key),因为返回的是number浮点数类型,会出现不精确情况。注意:类似数字大小已经快超时lua和reids最大数值,请谨慎的增加seq的位数--]]redis.call(\,key,incr_amoutt)redis.call(\,key)endendendget_max_seq()

以上的 lua 的脚本来自于Ydoing,一个博客的大佬,我们现在既然会使用他生成全局唯一的ID,那么是不是就得搞清楚为什么会选择 Redis 来实现分布式全局唯一的ID。

Redis 的所有命令是单线程的

上一段开头,阿粉就说 Redis 的命令都是单线程的,相信如果你在面试官面前这么说,面试官肯定会问你一句,为什么 Redis 是单线程而不是多线程的呢?

Redis 基于 Reactor 模式开发了网络事件处理器,这个处理器被称为文件事件处理器。它的组成结构为4部分:多个套接字、IO多路复用程序、文件事件分派器、事件处理器。因为文件事件分派器队列的消费是单线程的,所以 Redis 才叫单线程模型。

当你说到这个 Reactor 模式的时候,如果大家深入研究过 Netty 的模型,就会发现,这个模式在 Netty 中也是有使用的,我们这时候是不是就得需要去官网上去瞅瞅看,为什么这么说。

Reactor模型实际上都知道,就是一个多路复用I/O模型,主要用于在高并发、高吞吐量的环境中进行I/O处理。

而这种多路复用的模型所依赖的永远都是那么几个内容,事件分发器,事件处理器,还有调用的客户端

分布式全局唯一ID分布式全局唯一ID

Reactor模型是一个同步的I/O多路复用模型,我们还是先把这个同步的I/O多路复用模型给弄清楚了再看其他的。

这个相信大家肯定不是很熟悉,而阿粉在之前也给大家说了关于Netty中的Channel,文章地址发给大家,用Socket编程?我还是选择了Netty,在文章中,我们已经给大家说了关于Channel,而这种单线程的模型是什么样子的呢?

分布式全局唯一ID分布式全局唯一ID

图已经给大家画出来了,丑是丑了点,但是意思还是表达出来了。

这种模型也就是说:Redis 单线程指的是网络请求模块使用了一个线程(所以不需考虑并发安全性),即一个线程处理所有网络请求,其他模块仍用了多个线程。

而面试官还会有一种问法,为什么使用 Redis 就会快。

这个相信大家肯定能回答出来,因为 Redis 是一种基于内存的存储数据,为什么内存快?

因为这种快速是针对存储在磁盘上的数据来说的,因为内存中的数据,断电之后,消失了,你下次来的时候,不还是需要从磁盘读取出来,然后保存,所以说在Redis速度快。扯远了,回来继续说 Redis的单线程。

我们来看看官网给我们的解释:

分布式全局唯一IDRedisissinglethreaded.HowCanIexploitmultipleCPU/cores?It

其实翻译过来大致就是说,当我们使用 Redis 的时候,CPU 成为瓶颈的情况并不常见,因为 Redis 通常是内存或网络受限的。

其实说白了,官网就是说我们 Redis 就是这么的快,并且正是由于在单线程模式的情况下已经很快了,就没有必要在使用多线程了。这整的是不是就有点恶心了。阿粉也说说自己的见解,毕竟这官网的话有点糊弄人的意思。

其实 Redis 使用单个 CPU 绑定一个内存,针对内存的处理就是单线程的,而我们使用多个 CPU 模拟出多个线程来,光在多个 CPU 之间的切换,然后再操作 Redis ,实际上就不如直接从内存中拿出来,毕竟耗时在这里摆着。


对称加密和非对称加密的区别是什么?

l 对称加密算法对称加密算法是应用较早的加密算法,技术成熟。 在对称加密算法中,数据发信方将明文(原始数据)和加密密钥一起经过特殊加密算法处理后,使其变成复杂的加密密文发送出去。 收信方收到密文后,若想解读原文,则需要使用加密用过的密钥及相同算法的逆算法对密文进行解密,才能使其恢复成可读明文。 在对称加密算法中,使用的密钥只有一个,发收信双方都使用这个密钥对数据进行加密和解密,这就要求解密方事先必须知道加密密钥。 对称加密算法的特点是算法公开、计算量小、加密速度快、加密效率高。 不足之处是,交易双方都使用同样钥匙,安全性得不到保证。 此外,每对用户每次使用对称加密算法时,都需要使用其他人不知道的惟一钥匙,这会使得发收信双方所拥有的钥匙数量成几何级数增长,密钥管理成为用户的负担。 对称加密算法在分布式网络系统上使用较为困难,主要是因为密钥管理困难,使用成本较高。 在计算机专网系统中广泛使用的对称加密算法有DES、IDEA和AES。 传统的DES由于只有56位的密钥,因此已经不适应当今分布式开放网络对数据加密安全性的要求。 1997年RSA数据安全公司发起了一项“DES挑战赛”的活动,志愿者四次分别用四个月、41天、56个小时和22个小时破解了其用56位密钥DES算法加密的密文。 即DES加密算法在计算机速度提升后的今天被认为是不安全的。 AES是美国联邦政府采用的商业及政府数据加密标准,预计将在未来几十年里代替DES在各个领域中得到广泛应用。 AES提供128位密钥,因此,128位AES的加密强度是56位DES加密强度的1021倍还多。 假设可以制造一部可以在1秒内破解DES密码的机器,那么使用这台机器破解一个128位AES密码需要大约149亿万年的时间。 (更深一步比较而言,宇宙一般被认为存在了还不到200亿年)因此可以预计,美国国家标准局倡导的AES即将作为新标准取代DES。 l 不对称加密算法不对称加密算法使用两把完全不同但又是完全匹配的一对钥匙—公钥和私钥。 在使用不对称加密算法加密文件时,只有使用匹配的一对公钥和私钥,才能完成对明文的加密和解密过程。 加密明文时采用公钥加密,解密密文时使用私钥才能完成,而且发信方(加密者)知道收信方的公钥,只有收信方(解密者)才是唯一知道自己私钥的人。 不对称加密算法的基本原理是,如果发信方想发送只有收信方才能解读的加密信息,发信方必须首先知道收信方的公钥,然后利用收信方的公钥来加密原文;收信方收到加密密文后,使用自己的私钥才能解密密文。 显然,采用不对称加密算法,收发信双方在通信之前,收信方必须将自己早已随机生成的公钥送给发信方,而自己保留私钥。 由于不对称算法拥有两个密钥,因而特别适用于分布式系统中的数据加密。 广泛应用的不对称加密算法有RSA算法和美国国家标准局提出的DSA。 以不对称加密算法为基础的加密技术应用非常广泛。

如何入门 Python 爬虫

“入门”是良好的动机,但是可能作用缓慢。 如果你手里或者脑子里有一个项目,那么实践起来你会被目标驱动,而不会像学习模块一样慢慢学习。 另外如果说知识体系里的每一个知识点是图里的点,依赖关系是边的话,那么这个图一定不是一个有向无环图。 因为学习A的经验可以帮助你学习B。 因此,你不需要学习怎么样“入门”,因为这样的“入门”点根本不存在!你需要学习的是怎么样做一个比较大的东西,在这个过程中,你会很快地学会需要学会的东西的。 当然,你可以争论说需要先懂python,不然怎么学会python做爬虫呢?但是事实上,你完全可以在做这个爬虫的过程中学习python :D看到前面很多答案都讲的“术”——用什么软件怎么爬,那我就讲讲“道”和“术”吧——爬虫怎么工作以及怎么在python实现。 先长话短说summarize一下:你需要学习基本的爬虫工作原理基本的http抓取工具,scrapyBloom Filter: Bloom Filters by Example如果需要大规模网页抓取,你需要学习分布式爬虫的概念。 其实没那么玄乎,你只要学会怎样维护一个所有集群机器能够有效分享的分布式队列就好。 最简单的实现是python-rq:和Scrapy的结合:darkrho/scrapy-redis · GitHub后续处理,网页析取(grangier/python-goose · GitHub),存储(Mongodb)

svn和git的区别

区别1、GIT是分布式的,SVN不是这是GIT和其它非分布式的版本控制系统,最核心的区别;GIT跟SVN一样有自己的集中式版本库或服务器。 但,GIT更倾向于被使用于分布式模式,也就是每个开发人员从中心版本库/服务器上chectout代码后会在自己的机器上克隆一个自己的版本库。 区别2、Git直接记录快照,而非差异比较Git和其他版本控制系统的主要差别在于,Git 只关心文件数据的整体是否发生变化,而大多数其他系统则只关心文件内容的具体差异。 Git 并不保存这些前后变化的差异数据。 实际上,Git 更像是把变化的文件作快照后,记录在一个微型的文件系统中。 每次提交更新时,它会纵览一遍所有文件的指纹信息并对文件作一快照,然后保存一个指向这次快照 的索引。 为提高性能,若文件没有变化,Git不会再次保存,而只对上次保存的快照作一链接。 区别3、近乎所有操作都是本地执行在 Git 中的绝大多数操作都只需要访问本地文件和资源,不用连网。 但如果用 CVCS 的话,差不多所有操作都需要连接网络。 因为 Git 在本地磁盘上就保存着所有当前项目的历史更新,所以处理起来速度飞快。

本文版权声明本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,请联系本站客服,一经查实,本站将立刻删除。

发表评论

热门推荐