大厂Data+Agent 秘籍:腾讯/阿里/字节解析如何提升数据分析智能。 了解详情
写点什么

为什么总是需要无意义的 ID ?(二)

  • 2019-12-27
  • 本文字数:2139 字

    阅读完需:约 7 分钟

为什么总是需要无意义的 ID ?(二)

唯一性

消息队列往往需要对外保证服务质量,可能需要提供包括最多一次、最少一次和正好一次在内的服务质量,由于网络可能存在超时等不确定性,当我们想要实现正好一次时,就一定需要一种机制能够在接收方识别发送方发出的重复消息,在这时就需要使用唯一的标识符来解决这个问题:



我们在之前的系列文章 为什么 TCP 建立连接需要三次握手 提到的 TCP 连接中的序列号也是一个唯一的标识符,它能够帮助我们判断对数据进行去重,保证应用层的协议不会收到异常的数据包,这些场景都需要用到标识符的唯一性,唯一性为我们带来的就是精确识别对象的能力。


在与网络相关的场景下,使用唯一 ID 的例子非常普遍,假如我们想通过支付宝或者微信的 API 向其他人发起一笔转账,如果这次请求发生了超时,那么我的这笔转账请求到底有没有被处理呢?



当前的节点对于这笔转账请求的结果是不知道的,如果这时重新请求可能会发生二次转账这类严重的问题,但是如果不重新请求,转账可能没有生效,这时如果我们引入一个无意义的 ID 来帮助接收方识别请求的唯一性就能很好地解决这个问题:


  1. 如果接收方已经成功处理 ID 对应的请求,那么就直接返回;

  2. 如果接收方没有处理 ID 对应的请求,就正常进行处理;


为了保证请求的唯一性,根据业务对于唯一性要求的强弱,我们需要在接收方对 ID 进行存储,可以在内存中,也可以在数据库中,最重要的是唯一的 ID 为接收方提供了判断重复的重要依据。


除了在不稳定的网络中,数据库也包含 ID 标识符这一概念,我们在数据库中往往叫做主键,它在一般情况下都是一个递增的唯一整数,绝大多数的表都会使用 ID 作为表的主键来保证数据的唯一性,当我们想要对数据进行增删改查等操作时,使用主键 ID 查询数据也是性能最优并且最不容易出现问题的做法。

无意义

无意义的意思其实就是 ID 中不应该包含任何与具体场景或者业务相关的内容,包含这些内容并不是不可以,只是一旦出现这些内容,要么 ID 重复的可能性会增加,这很可能对我们的业务逻辑造成比较严重的影响,以我们的身份证号为例,它的 18 位数字(或符号)大多都是有意义的。



这 18 位数字中的前 6 位表示的是地区,也就是省份、城市和区县,随后的 8 位表示的是出生年月日,接下来的 3 位才同时表示 ID 和性别,最后 1 位用于做校验码防止出现身份证号输错的情况。用上述图中的黄色部分中有一半的数字是用来表示出生的男性,另一半表示出生的女性,所以如果同一个地区的同一天,同时出生了 501 位男性或者女性就会导致潜在的重复问题。


上面谈到的问题其实也是我们在各种业务场景中经常能够遇到的问题,18 位的数字中真正用于表示序列的 ID 其实只有 1000 的一半,如果 18 位数都是无意义的,那它们可以表示 10 亿亿个人,但是一旦在 ID 中引入了业务上的具体信息,就增加了冲突的可能性。


业务记录上主键的长度往往都是固定的,大多数业务的主键都会使用整数,它的上限一般就是 2^64,如果这些位数都用来表示记录的 ID,那么在有生之年基本上是不可能被使用完的,但是一旦我们将业务信息加入 ID,就会让原本无意义的 ID 变得有意义从而影响它的唯一性。


另一个比较类似的例子其实是分布式的 ID 生成器,Snowflake 算法会为 64 个比特的整数赋予不同的信息:


范围长度作用
0-01不使用
1-4141毫秒级时间戳
42-465数据中心标识符
47-515机器标识符
52-6312序列号


从这个设计来看,我们的假设其实是一台机器上一毫秒最多只能生成 4096 个 ID,一旦超过了这个这个数量就有可能导致 ID 冲突或者乱序,从而失去其唯一性;这个算法中涉及的时间戳、数据中心标识符、机器标识符都没有办法解决唯一性的问题,哪怕这三者完全相等,最终还是有冲突的可能,我们仍然需要使用无其他意义的序列号来保证 ID 的唯一。

总结

其实不难看出,使用无意义 ID 的主要目的就是利用它的唯一性保证对象的标识符不会发生冲突,无意义 ID 的唯一作用就是保证唯一性,这能帮助我们避免业务字段可能存在潜在冲突的可能,这也提示我们想要使用联合字段构成主键时一定要深思熟虑。


如果我们想要在具有唯一性的标识符中加入业务信息,一定要注意这可能会减少用于保证唯一性的『空间』,当然对于一个足够大的空间来说,这其实并没有什么问题;但是类型为 int64 的 ID 中加入业务数据还是需要仔细思考可扩展性以及预留的信息是否足够业务的发展。


到最后,我们还是来看一些比较开放的相关问题,有兴趣的读者可以仔细思考一下下面的问题:


  • 软件工程还有哪些场景利用了 ID 的唯一性?

  • 在日常生活中除了身份证号之外,还有哪些 ID 也有比较高的冲突可能性?


如果对文章中的内容有疑问或者想要了解更多软件工程上一些设计决策背后的原因,可以在博客下面留言,作者会及时回复本文相关的疑问并选择其中合适的主题作为后续的内容。

相关文章


本文转载自 Draveness 技术博客。


原文链接:https://draveness.me/whys-the-design-meaningless-identifier


2019-12-27 11:331071

评论

发布
暂无评论
发现更多内容

马云:今天的区块链并没有被人们认识到价值!

CECBC

区块链 阿里巴巴 马云

Linux命令netstat详解

5加3彩票

【在云端 003】 星星之火,可以燎原——云时代的IoT

Bora.Don

云计算 IoT AIOT

java安全编码指南之:Number操作

程序那些事

java安全编码 java安全 安全编码规范

Go语言 sync.Mutex 源码分析

5加3彩票

Go 语言

理解大端字节和小端字节

5加3彩票

bit比特, Byte字节,基础知识

5加3彩票

synchronized实现原理及代码证明各种锁

Darren

源码 synchronized 轻量级锁 偏向锁 Monitor

第13周学习总结

刘卓

ZIP 也能边下载边解压?优酷流式解压技术揭秘

阿里文娱技术团队

ZIP

遇到银河提现不了网站维护审核怎么办?

丛林里的余光

数据库 网站平台 提现

GO语言 MD5 四种实现方式

5加3彩票

Go 语言

Docker Compose 搭建 Redis Cluster 集群环境

哈喽沃德先生

redis Docker Docker-compose redis集群 redis cluster

第13周作业

刘卓

PHP配置管理-yaconf

5加3彩票

php

epoll的原理和流程

5加3彩票

PageRank

GalaxyCreater

教师节送什么老师最开心?程序员三招解决家长送礼难题!

华为云开发者联盟

编程 程序

开始编译第一个typescript实例

程序员学院

Java typescript 大前端

云栖大会边缘计算分论坛倒计时7天,这2点值得期待

阿里云Edge Plus

边缘计算

GO 语言异常处理

5加3彩票

Go 语言

GO 语言交叉编译

5加3彩票

Go 语言

Redis哨兵(sentinel )机制讲解

5加3彩票

从零开始搭建完整的电影全栈系统(三)——restfulApi的编写

刘强西

RESTful 电影api

PHP Db类强制读主库(master)的设计

5加3彩票

php MySQL

聊聊开发工程师如何转型产品经理

长沙造纸农

程序员 开发者 产品经理 转型 中年危机

MYSQL中时间类型底层存储,DATETIME ,TIMESTAMP,INT 如何选择?

5加3彩票

TCP三次握手和四次挥手

5加3彩票

关于第四次财富狂潮的思考,区块链如猛虎出笼?

CECBC

比特币 区块链 数字货币

GO 语言超时实现

5加3彩票

Go 语言

Centos 上配置大数据环境

yuanhang

大数据

为什么总是需要无意义的 ID ?(二)_文化 & 方法_Draveness_InfoQ精选文章