求个尽量均匀的分区算法

2021-03-19 05:06:59 +08:00
 Rocketer

由于数据量庞大,打算分区存储,希望有个高效且尽量均匀的分区算法。

比如有 1 亿条数据,100 个区,那最好每个区都能分到 100 万条左右的数据,越接近越好。

数据的主键是长度为 12 的字符串,我试过把每个字符的 ASCII 码加起来再取模,结果发现均匀度很差,热区能比冷区多 50 倍。

求各位大神推荐个算法,不胜感谢

3934 次点击
所在节点    程序员
33 条回复
ETiV
2021-03-19 05:25:47 +08:00
数据的主键是长度为 12 的字符串

特征得再详细点:是递增的吗?是随机的吗?是 uuid/guid 算出来的吗?中间有表示 timestamp 含义的吗?等等…
MegrezZhu
2021-03-19 05:50:09 +08:00
hash 取模?
Rocketer
2021-03-19 05:51:27 +08:00
@ETiV 前 3 位是表示数据类型的,相对集中,我看了一下大概只有 10 几种在用的组合。后 9 位是递增的。
Rocketer
2021-03-19 05:52:42 +08:00
@MegrezZhu 我求的本质上就是个 hash 算法呀,还是说你指的是那些通用 hash 算法,md5 之类的?
abcdabcd987
2021-03-19 05:54:41 +08:00
uniform hash % 100?
MegrezZhu
2021-03-19 05:56:44 +08:00
@Rocketer 嗯对
Rocketer
2021-03-19 06:05:11 +08:00
@abcdabcd987 我求的就是这个 uniform hash,有没有具体的思路或代码呢?
Rocketer
2021-03-19 06:11:28 +08:00
@MegrezZhu 试过 md5,确实均匀多了,但有点用 40 米的大砍刀杀鸡的感觉,一个分区算法不应该用那么大的计算量
xuegy
2021-03-19 06:17:49 +08:00
多迭代几次就均匀了。打个比方:你放一坨面里面放一个无限小的小球,然后开始拉面。拉上几次你就不知道那个小球在哪了。
abcdabcd987
2021-03-19 06:19:11 +08:00
@Rocketer 我觉得可以先试试常用的 non-crypto hash % 100 看均匀不均匀吧,比如像 libstdc++ 用的就是 Murmur Hash,或者简单粗暴好实现的 FNV Hash 。实在不行也可以试试看 MD5,虽然 MD5 在密码学上面看不太行,但是作为普通的 hash function 来用一般还是认为挺均匀的。

刚刚搜了一下,这里有篇文章做了一下实验,结论是 Murmur Hash 和 MD5 都挺均匀的: https://www.rolando.cl/blog/2018/12/how_uniform_is_md5.html
aec4d
2021-03-19 08:08:44 +08:00
找一致性 hash 算法,虚拟节点,siphash
Rocketer
2021-03-19 08:38:15 +08:00
@aec4d 谢谢,概念问题我都懂,就是需要一个具体的好用的算法
shuax
2021-03-19 08:46:07 +08:00
crc16 也能用嘛
binux
2021-03-19 08:46:16 +08:00
LessonOne
2021-03-19 09:15:17 +08:00
参考下 Java 8 HashMap hash 算法
0ZXYDDu796nVCFxq
2021-03-19 09:17:48 +08:00
每个区存 100 万,存满了再用下一个
对于一些按时间区域查询,效率更高
knightdf
2021-03-19 09:21:19 +08:00
fnv1a hash
qqq8724
2021-03-19 09:25:35 +08:00
RangePartitioner
FakNoCNName
2021-03-19 09:43:20 +08:00
你是想做类似: 分区 Id = Num % 100 。这种能快速简单计算的运算吗?

看你在 3 楼说的字符串后 9 位是递增的,这样的话就简单了,取字符串最后 2 位,转成数字 Num,用 Num % 100 就是你想要的结果。

如果你的字符串后 9 位不是 10 进制的,也可以按照类似的逻辑转化处理下,当然要注意分区数量是进制的整数倍,不然就会出现一部分数据过于集中的情况。
yeguxin
2021-03-19 09:58:14 +08:00
首先查询的场景多不多,如果只是考虑单纯的均匀度合适问题要不要考虑 HashMap 处理 key 落到具体的桶的算法?
(h = key.hashCode()) ^ (h >>> 16) 通过高低位扰动来提高随机性。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/763030

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX