如何生成唯一id-极全网
返回
顶部

修改密码

首页 > 文章 > 财经 > 正文
如何生成唯一id

+1

-1

收藏

+1

-1

点赞0

评论0

标题:如何生成唯一id
详情介绍-作者:xiaowei-来源: 极全网 -如有问题点击:在线客服帮助

1.设计分布式唯一id生成


当db不& amp#039;它不会自动为您生成。例如:

A.不依赖第三方的唯一id生成服务,利用业务db的特性生成id。

例如,在& ampquot订单表& ampquot对一个业务划分为仓库和表,如果你想要一个全局唯一的订单id,你可以使每个仓库在划分后根据不同的起点和步长增加。通过这种方式,订单系统可以自行解决问题,而不依赖于发布服务。

缺点是db的伸缩太复杂。

另一个思路是每个子表都有一个前缀,这个前缀在子表中是自增的。

其实这样可以避免膨胀收缩的问题。比如分片策略就是预先划分1000个表,每个表的id都有一个通用前缀,表中的id自己增加。

B.去中心化方案,机器标识(比如mac地址)作为命名空间,通过命名空间保证唯一性。

比如3360

C.集中化方案,实现了唯一的id生成服务和基于写操作的线性一致存储。

比如利用mysql的自增特性做一个sender服务。

例如,随机地,写入线性化内存中的cas,如果写入成功,则申请id。

如果吞吐量过大,存储有压力,可以给存储增加一个缓存,提前向存储申请多个id(号段)。这个缓存没有。#039;不需要redis等。只需启动一个java程序作为进程内缓存。

例如,很难向nosql这样的时间戳字段添加索引。分页查看最新数据时,只希望按id查看。

Q:类雪花算法基于时间戳命名空间。时钟回调怎么办?

(闰秒,NTP时钟同步等。都可能导致时钟回调)

A.外部存储器记录最新的时间戳并检测回调。比如美团外有个zk。

b.在最终写入线性化存储器时检测重复,并报告错误以重复重复。

C.再添加几个名称空间,使概率可以忽略不计。

如何在Q:雪花中生成workerId

A.基于线性化的存储

比如美团方案连接一个zk,每台机器依次取workerId(依机器而定);

但是这太重了,所以您可以将workerId更改为业务Id。其思想是通过命名空间来降低概率,而不是绝对唯一。

B.没有必要使用机器id。本质上,只需添加一个名称空间和一些业务字段作为名称空间。

我们之前使用的方案是,除了时间戳之外,在id中加入Uid、业务类型、随机数等一些字段作为命名空间,以降低概率。

Q:分布式关系数据库能否自动生成全局单调递增的唯一id?

Tidb看的只是单机增量,没有办法保证全局单调增量:

& amp的两个保证。quot增长趋势& ampquot和& ampquot全球单调递增和。quot处于两个极端。我们能在他们之间给一个保证吗?

基于体系结构的分布式ID生成方法探讨

美团点评Leaf——分布式ID生成系统



2.如何为每部Android手机生成一个唯一的ID


这种方法是,以一些特定的信息为基础,生成设备的唯一标识。


首先,算法角度,常用的有UUID、摘要两种。这两种算法都是以特定的数据为基础,生成一个唯一的、固定长度的字符串。这里选择UUID。

其次,计算的基础数据,建议选择divice_id和android_id。原因是,1)这两个标识虽然不能抵抗wipe操作,但受用户的行为影响比较小;2)如果正常获取,都是唯一的;③如果不能正常获取,结果也是固定的,不会频繁变化。

再次,优先级的考虑。从这两个标识的缺点考虑。

1)device_id。

①不能标识非手机设备,例如Pad。

②权限问题,因为用户的反感。

③获取异常,厂商定制系统中存在的bug,致使返回结果为空,或者为一串“0”或“*”。

④对于双卡双待手机,会返回两个device_id。

2)android_id。

①Android2.3以前,系统Bug,导致不同的设备产生相同的结果:

9774d56d682e549c。

②有些可能返回null。

③设备差异:对于CDMA设备,与device_id返回相同的值。

综合考虑,device_id不能标识某些pad,以及用户的权限问题,是我们不能接受的,所以优先使用android_id。对于android_id返回为null的情况,再考虑使用device_id。

最后,当android_id和device_id都返回异常的情况,我们可以随机生成一个UUID。



3.如何在高并发分布式系统中生成全局唯一Id


我了解的方案如下……………………………………………………………………


1、 使用数据库自增Id

优势:编码简单,无需考虑记录唯一标识的问题。

缺陷:

1) 在大表做水平分表时,就不能使用自增Id,因为Insert的记录插入到哪个分表依分表规则判定决定,若是自增Id,各个分表中Id就会重复,在做查询、删除时就会有异常。

2) 在对表进行高并发单记录插入时需要加入事物机制,否则会出现Id重复的问题。

3) 在业务上操作父、子表(即关联表)插入时,需要在插入数据库之前获取max(id)用于标识父表和子表关系,若存在并发获取max(id)的情况,max(id)会同时被别的线程获取到。

4) 等等。

结论:适合小应用,无需分表,没有高并发性能要求。

2、 单独开一个数据库,获取全局唯一的自增序列号或各表的MaxId

1) 使用自增序列号表

专门一个数据库,生成序列号。开启事物,每次操作插入时,先将数据插入到序列表并返回自增序列号用于做为唯一Id进行业务数据插入。

注意:需要定期清理序列表的数据以保证获取序列号的效率;插入序列表记录时要开启事物。

使用此方案的问题是:每次的查询序列号是一个性能损耗;如果这个序列号列暴了,那就杯具了,你不知道哪个表使用了哪个序列,所以就必须换另一种唯一Id方式如GUID。

2) 使用MaxId表存储各表的MaxId值

专门一个数据库,记录各个表的MaxId值,建一个存储过程来取Id,逻辑大致为:开启事物,对于在表中不存在记录,直接返回一个默认值为1的键值,同时插入该条记录到table_key表中。而对于已存在的记录,key值直接在原来的key基础上加1更新到MaxId表中并返回key。

使用此方案的问题是:每次的查询MaxId是一个性能损耗;不过不会像自增序列表那么容易列暴掉,因为是摆表进行划分的。

详细可参考:《使用MaxId表存储各表的MaxId值,以获取全局唯一Id》

我截取此文中的sql语法如下:


第一步:创建表

create table table_key

(

table_name varchar(50)not null primary key,

key_value int not null

)

第二步:创建存储过程来取自增ID

create procedure up_get_table_key

(

@table_name varchar(50),

@key_value int output

)

as

begin

begin tran

declare @key int


--initialize the key with 1

set @key=1

--whether the specified table is exist

if not exists(selecttable_name from table_key wheretable_name=@table_name)

begin

insert into table_keyvalues(@table_name,@key) --default key vlaue:1

end

-- step increase

else

begin

select @key=key_valuefrom table_key with (nolock) where table_name=@table_name

set @key=@key+1

--update the key value by table name

update table_key setkey_value=@key where table_name=@table_name

end

--set ouput value

set @key_value=@key


--commit tran

commit tran

if @@error>0

rollback tran

end

转载仅供参考,版权属于原作者。

版权声明:本文内容由极全网实名注册用户自发贡献,版权归原作者所有,极全网-官网不拥有其著作权,亦不承担相应法律责任。具体规则请查看《极全网用户服务协议》和《极全网知识产权保护指引》。如果您发现极全网中有涉嫌抄袭的内容,点击进入填写侵权投诉表单进行举报,一经查实,极全网将立刻删除涉嫌侵权内容。

扫一扫在手机打开

评论
已有0条评论
0/150
提交
热门评论
相关推荐
换一批
热点排行