== 星球水友提问 ==
沈老师,你好,想请教一个身份证信息检索的问题。
公司有一个每秒 5 万并发查询的业务,(假设)根据身份证 MD5 查询身份证信息,目前有 1000 亿条数据,纯文本存储,前几天看你写 LevelDB,请问这个业务能利用 LevelDB 内存数据库进行存储么?有没有其他优化方案?
画外音:LevelDB_《内存 KV 缓存 / 数据库》。_
== 问题描述完 ==
上一位星球水友问的是 36 亿日志后台分页查询,紧接着又来了一位 1000 亿文本 MD5 查询,这次的业务,至少需要解决:
(1)查询问题;
(2)高性能问题;
(3)存储问题;
一、查询问题
文本信息的查找与检索,效率很低,第一个要解决的问题是:将文本过滤转变为结构化查询。
由于检索条件是 MD5,可以结构化为:
(MD5, data)
这样可以 KV 查询,或者数据库里的索引查询。
需要注意的是,MD5 一般为字符串表示,字符串作为索引性能会降低,可以将字符串型的 MD5 转化为两个 uint64_t 进行存储,以提高索引效率。
(md5_high, md5_low, data)
两个长整形做联合索引,或者 KV 中的联合 key。
该业务有一个很强的特点,都是单行数据主键上的查询,抛开数据量不说,即使不使用缓存,传统的关系型数据库存储,单机也能扛至少 1W 的查询。
_画外音:_但其实单机存不下,后文细说。
二、高性能问题
每秒 5W 并发,吞吐量很大,第二个要解决的是:性能的提升。
身份证查询的业务有两个很强的特点:
(1)被查询的数据是固定的;
(2)只****有查询请求,没有修改请求;
很容易想到,缓存非常非常适合这种场景,不仅如此,还可以提前将数据加载到内存里,规避缓存的 “预热”。
画外音:根据业务特点做设计,任何脱离业务的架构设计都是耍流氓。
如果内存足够大,提前加载数据,可以做到缓存命中率 100%;即使不提前加载,每条数据也最多一次 cache miss,数据一旦入 cache,由于没有写请求,后续将永远不会被换出。
内存足够大的前提成立么?
假设每张身份证信息 0.5K,1000 亿大约:
1000 亿 * 0.5K = 50000G = 50T
画外音:没有算错吧?
如此来看,如果不是特别土豪,缓存装不下所有数据,只能承载热数据。
每秒 5W 的吞吐量是瓶颈么?
线性扩充容量的方法很多:
(1)站点、服务冗余 10 份以上;
(2)存储(主键单行查询)水平切分 10 份以上;
可以看到,5W 的并发并不是问题。
三、存储问题
如上一个部分分析,1000 亿身份证信息,50T 的数据,数据量实在太大,传统的关系型数据库,LevelDB 此类单机内存数据库不是特别合适,人工水平切分,拆分实例会非常多,较难维护。
还是使用 Hbase 这类适合大数据量的存储技术吧。
最终,结合本例,建议:
(1)千万不能文本检索,务必要结构化;
(2)单行查询,只读不写,缓存 + 冗余 + 水平切分能极大提升吞吐量;
(3)使用适合海量数据的技术进行存储;
经验有限,欢迎大家贡献更多更好的方案。
思路比结论重要。
课后习题:
1000 亿数据,不同的身份证号可能导致 MD5 重复,怎么办?