求个尽量均匀的分区算法
由于数据量庞大,打算分区存储,希望有个高效且尽量均匀的分区算法。
比如有 1 亿条数据,100 个区,那最好每个区都能分到 100 万条左右的数据,越接近越好。
数据的主键是长度为 12 的字符串,我试过把每个字符的 ASCII 码加起来再取模,结果发现均匀度很差,热区能比冷区多 50 倍。
求各位大神推荐个算法,不胜感谢
由于数据量庞大,打算分区存储,希望有个高效且尽量均匀的分区算法。
比如有 1 亿条数据,100 个区,那最好每个区都能分到 100 万条左右的数据,越接近越好。
数据的主键是长度为 12 的字符串,我试过把每个字符的 ASCII 码加起来再取模,结果发现均匀度很差,热区能比冷区多 50 倍。
求各位大神推荐个算法,不胜感谢
特征得再详细点:是递增的吗?是随机的吗?是 uuid/guid 算出来的吗?中间有表示 timestamp 含义的吗?等等…
刚刚搜了一下,这里有篇文章做了一下实验,结论是 Murmur Hash 和 MD5 都挺均匀的: https://www.rolando.cl/blog/2018/12/how_uniform_is_md5.html
看你在 3 说的字符串后 9 位是递增的,这样的话就简单了,取字符串最后 2 位,转成数字 Num,用 Num % 100 就是你想要的结果。
如果你的字符串后 9 位不是 10 进制的,也可以按照类似的逻辑转化处理下,当然要注意分区数量是进制的整数倍,不然就会出现一部分数据过于集中的情况。
while (*str)
{
hash = hash * seed + (*str++);
}
return (hash & 0x7FFFFFFF);
这个 hash 要求速度极快,所以还是要在基本算法上做文章。最后采取了反向活跃加权再取模的办法,目前测试效果还不错。
思路说起来也很简单,对字符串中的每一位,越常变化的权重越低,比如最活跃的权重是 C,第二活跃的权重是 C*C……各字符加权求和后再%100,就行了。权重常数 C 从 2 到 100 用真实数据测一遍,就能找到最适合的了。现在各区都在正负 10%内,很满意了。