hash的讨论

本文详细探讨了哈希函数、冲突处理、布隆过滤器和分布式一致性哈希。讨论了负载因子对冲突概率的影响,以及链表法和开放地址法解决冲突的策略。介绍了布隆过滤器的工作原理、参数计算及其应用场景,强调其在减少无效访问中的作用。此外,还触及了分布式一致性哈希在解决数据分布和集群扩展问题上的挑战及解决方案。
摘要由CSDN通过智能技术生成

讨论问题:

1、hash函数与冲突处理。

2、hash表

3、布隆过滤器

4、分布式一致性hash

hash的负载因子:hash已经存储的元素的个数。

hash冲突:不同的key值利用hash函数计算出的hash值对应的容器索引。负载因子越小冲突的概率越小,负载因子越大冲突的概率越大。

hash聚集:近似的key值的hash值也近似。解决冲突的时候,可能会导致严重的hash聚集现象。

冲突解决方式:

1、链表法:

a、头插法(一般用于数据库,数据库因为认为刚刚插入的元素最近会更加容易访问到)

b、尾插法

c、当链表过长可以把链表转化成红黑树或者avl树。

2、开放地址法:

a、i+1i+2i+3、...、i+n等探查下去直到探查完成。

b、i-1^2i+2^2i-3^2、... 等探查下去知道探查完成。

c、双重哈希(避免hash聚集现象):Hk(key) = [GetHash(key)+k*(1+(((GetHash(key)>>5)+1)%(hashszie-1)))]%hashsize

数学原理:https://www.cnblogs.com/organic/p/6283476.html

布隆过滤器:

用n个哈希函数来对key做运算得到n个位置分别映射到位图上(位图是个数组,元素只有0或者1两个状态)。布隆过滤器只能判断一个key可能存在或者一定不存在。用n个哈希函数对key做运算后判断n个对应位置是否存在0状态,如果存在就是key一定不存在,否则可能存在。

如何使用布隆过滤器:

1、要预估key的数量n

2、误差概率p。

3、位图元素个数m。

4、哈希函数的个数k。

公式:

n = ceil( m / ( -k / log(1 - exp( log(p) / k ))))

p = pow(1 - exp(-k / (m/n)), k)

m = ceil((n * log(p)) / log(1 / pow(2, log(2))))

k = round((m / n) * log(2))

数学原理:http://hur.st/bloomfilter

使用布隆过滤器的时候先确认n和p然后通过上面的网址计算出合适的m和k。

 哈希函数的分布性与质数相关,在17,31,101中31的分布性最好。

哈希函数:murmurhash1, murmurhash2,murmurhash3、siphash(redis6.0当中使用),cityhash。siphash主要解决字符串接近的强随机分布性。

测试地址:https://github.com/aappleby/smhasher

k个哈希函数的生成:

#define MIX_UINT64(v) ((uint32_t)((v>>32)^(v))

uint64_t hash1 = MurmurHash2_x64(key, len, seed);
uint64_t hash2 = MurmurHash2_x64(key, len, MIX_UINT64(hash1));

for(i = 0; i < k; i++)
{
    Pos[i] = (hash1 + i*hash2) % m;
}

布隆过滤器主要解决的场景是可以过滤大多数不存在的访问,但是有一个可控的错误概率。可能访问1000次不同不存在的数据可能有1次的概率需要真正的访问,大概率排查不存在的数据。这个可以减少不存在数据的真正访问次数,提高效率。

分布式一致性hash:

在一个分布式数据缓存的集群中,有n个节点作为缓存服务器。用hash(ip:port)%2{^{32}}来算出n个节点的hash值cache_hash_n,它们全部落到0到2{^{32}}-1的圆环中。ip是节点的ip地址,port是节点的端口号。之后用hash(key)%2{^{32}}来算出需要缓存的数据的key的hash值data_hash,然后从data_hash开始找下一个最近的cache_hash_n,找到后就把数据存储到cache_hash_n对应的缓存服务器中。

分布式一致性hash主要解决分布式缓存的数据均匀分布与横向扩展集群的问题:
在最开始的分布式数据缓存集群有n个节点,通过hash来确定数据缓存在哪个节点上。随着访问的数据越来越多每个节点的压力越来越大,那么就需要扩展节点。由于hash的计算公式是hash(key)%n,那么扩展节点后增加了k个节点,所以公式变成了hash(key)%(n+k)这个时候hash值就乱套了。

分布式一致性hash的问题:

1、会造成部分数据存储的影响:

(通过数据迁移来解决 http://github.com/metang326/consistent_hashing_cpp

还是上面的例子,如果有n个节点,那么增加1个节点后,新的节点的hash值new_hash会落到圆环的某个位置,假设新节点的前后节点的hash值为pre_hash和next_hash,原先落在pre_hash与next_hash之间的数都是存储到next_hash对应的节点上的,那么现在添加了new_hash后pre_hash与new_hash之间的数据就存储到new_hash上。

2、hash偏移,数据分布不均匀。(通过增加虚拟节点解决)

一上面的例子为例,由于n个节点的结点数量太少,所以在圆环上的节点分布不均匀,从而导致数据分布不均匀。那么解决的方案是,为每个节点添加虚拟节点,虚拟节点的hash值为hash(ip:port:n)%2{^{32}}。当节点足够多的时候,节点就能均匀分布在圆环上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值