你好,我是风一样的树懒,一个工作十多年的后端专家,曾就职京东、阿里等多家互联网头部企业。公众号“吴计可师”,已经更新了过百篇高质量的面试相关文章,喜欢的朋友欢迎关注点赞
这个问题直击分布式系统设计的核心矛盾,下面从技术本质、业务场景、设计哲学、面试意图四个维度为你深度解析
一、技术本质对比
1. ES内置_id特性
graph LR
A[写入请求] --> B{是否提供_id?}
B -->|是| C[使用客户端指定ID]
B -->|否| D[ES自动生成UUID]
D --> E[基于版本号冲突检测]
C --> F[基于_create操作幂等控制]
优势:
- 自动生成全局唯一ID(Version 4 UUID)
- 天然支持幂等写入(配合
op_type=create) - 无需客户端额外计算开销
缺陷:
- 无法实现跨系统ID统一(业务主键丢失)
- 随机UUID导致分片路由不均(热点问题)
- 长字符串存储开销大(比数字大4倍)
2. 自定义ID方案
典型实现:
- 雪花算法(Snowflake)ID
- 业务主键拼接(
order_2023080110001) - 数据库自增ID映射
优势:
- 分片路由优化(如用用户ID做分片键)
- 业务关联性强(直接携带业务信息)
- 存储空间更小(Long vs String)
缺陷:
- 额外ID生成系统复杂度
- 跨系统同步风险(ES与DB不一致)
- 需自行解决冲突(如重试策略)
二、业务场景决策树
graph TD
A[业务场景] --> B{需要强业务关联?}
B -->|是| C[自定义ID]
B -->|否| D{写入量级?}
D -->|超高频 >10w/s| E[ES内置ID]
D -->|中低频| F{是否需跨系统同步?}
F -->|是| C
F -->|否| E
经典选型案例:
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| 日志分析系统 | ES内置ID | 无业务含义,高吞吐优先 |
| 电商订单检索 | 自定义ID | 用订单ID直接检索,路由均匀化 |
| 用户画像存储 | 混合方案 | UserID作_id,业务标签作字段 |
| 物联网传感器数据 | ES内置ID | 避免设备ID稀疏性导致分片倾斜 |
三、面试官的真实意图
1. 表层考察:技术方案对比
- 是否了解两种方案的底层实现差异
- 能否说清UUID和Snowflake的算法原理
2. 中层考察:架构设计能力
- **数据一致性**:
“当数据库与ES使用不同ID时,如何保证双写一致性?”
- **扩展性**:
“百亿数据量下,自定义ID如何避免分片热点?”
- **成本控制**:
“字符串ID比数字ID多消耗多少存储?”
3. 深层考察:工程哲学理解
- **取舍思维**:
“在CAP框架下,ID生成选择如何影响ES的可用性?”
- **抽象能力**:
“能否从ID方案延伸到分布式系统全局唯一ID设计?”
- **故障预见**:
“如果选错ID方案,可能导致什么生产事故?”
四、面试应答模板
回答框架:
1. **技术对比**:简述两种方案特点
2. **场景分析**:给出决策依据
3. **实战案例**:举例说明选择逻辑
4. **延伸思考**:展现架构视野
参考话术:
“关于ID方案的选择,我认为需要分场景决策:
ES内置ID适合日志、监控类场景,它能简化客户端逻辑,例如Kibana的日志流直接依赖自动生成的
_id。但需注意随机ID会导致分片路由不均,可通过routing参数优化。自定义ID更适合强业务关联场景,比如电商订单检索直接用
order_id作为_id,这样既能实现跨系统ID统一,又能利用订单ID中的用户哈希值天然均匀分片。在去年设计的舆情系统中,我们采用混合方案:
- 用Snowflake生成数字ID作
_id(避免UUID存储膨胀)- 将文章URL的MD5作为业务主键字段
既保证写入性能,又支持按URL精准检索。从更高维度看,ID设计本质是一致性、扩展性、成本的三角平衡。如果重新设计,我会考虑用
ZoneId+时间戳+序列号的复合ID,在跨数据中心场景下可能更具优势。”
五.高频追问清单
-
“为什么ES不推荐用数据库自增ID?”
→ 答:自增ID无法分散分片,导致写入热点 -
“如何实现自定义ID的分布式唯一?”
→ 答:结合Redis原子操作+数据库号段 -
“
_id字段能用数字类型吗?”
→ 答:ES底层强制转为字符串,但数字可压缩存储
今天文章就分享到这儿,喜欢的朋友可以关注我的公众号,回复“进群”,可进免费技术交流群。博主不定时回复大家的问题。
公众号:吴计可师