海量数据去重的Hash、BloomFilter、bitmap

 从海量数据中查询某个字符串是否存在?

平衡二叉树

增删改查时间复杂度为 O(log2n),100万个节点最多比较20次,10亿个节点最多比较30次;

平衡的目的是增删改后,保证下次搜索能稳定排除一半的数据;

通过比较保证有序,通过每次排除一半的元素达到快速索引的目的。

散列表

        根据 key 计算 key 在表中的位置的数据结构;是 key 和其所在存储地址的映射关系;

struct node {
  void *key;
  void *val;
  struct node *next;
};

注:其中K\V存储在一起;

hash函数

        Hash(key) = addr;

        哈希函数可能会把两个或两个以上的不同key映射到同一地址,这种情况称为哈希冲突(哈希碰撞)

选择哈希

  • 计算效率高; 
  • 强随机分布(等概率,均匀地分布在整个地址空间);
  • murmurhash1,murmurhash2,murmurhash3,siphash(redis6.0当中使⽤,rust等大多数语言选用的hash算法来实现hashmap),cityhash 都具备强随机分布性;测试地址
  • siphash 主要解决字符串接近的强随机分布性;

负载因子

  •         数据存储元素的个数 / 数据长度;
  •         用来形容散列表的存储密度;
  •         负载因子越小,冲突越小;负载因子越大,冲突越大;

冲突处理

  • 链表法

        引用链表来处理哈希冲突;也就是将冲突元素用链表链接起来;这也是常用的处理冲突的⽅

式;但是可能出现一种极端情况,冲突元素比较多,该冲突链表过长,这个时候可以将这个链表转换为红黑树;由原来链表时间复杂度 转换为红黑树时间复杂度 ;那么判断该链表过长的依据是多少?可以采⽤超过 256(经验值)个节点的时候将链表结构转换为红黑树结构;

  • 开放寻址法

        将所有的元素都存放在哈希表的数组中,不使用额外的数据结构;一般使用线性探查的思路
解决;

  1. 当插入新的时,使哈希函数在哈希表中定位元素位置;
  2. 检查数组中该槽位索引是否存在该元素。如果该槽位为空,则插入,否则进行第3步;
  3. 在第2步检测的槽位索引上加一定步长接着检查第2步;
  • i+1,i+2,i+3,i+4, ... ,i+n
  • i- ,i+ ,i- ,1+ , ...
  • 这两种都会导致同类 hash 聚集;也就是近似值它的hash
    值也近似,那么它的数组槽位也靠近,形成 hash 聚集;第一种同类聚集冲突在
    前,第二种只是将聚集冲突延后; 另外还可以使用双重哈希来解决上面出现hash
    聚集现象:

布隆过滤器

        布隆过滤器是一种概率型数据结构,他的特点是高效地插入和查询,能确定某个字符串一定不存在或者可能存在。

        布隆过滤器不存储具体数据,占用空间小,查询存在可控误差,同时不支持删除操作。

构成

        位图(BIT数组)+ n个哈希函数

        

原理

        当一个元素加入位图时,通过k个哈希函数将这个元素映射到位图的k个点,并把他们置位1;

        当检索时,再通过k个哈希函数运算检测位图k个点是否都为1;如果有不为1的点,那么认为该key不存在;如果全部为1,则可能存在。

        在位图每个槽位只有两个状态(0或1),一个槽位被设置为1状态,但不确定它被设置了多少次;也就是不知道多少个哈希映射而来以及具体是被哪个哈希函数映射而来。

 应用场景

        布隆过滤器常用于判断某个key一定不存在的场景,同时允许判断存在时有误差的情况;

        常见处理场景:

  1. 缓存穿透的解决;
  2. 热key限流;

  • 缓存场景,为了减轻数据库(mysql)的访问压力,在server端与数据库(mysql)之间加入缓存用来存储热点数据;
  • 缓存穿透,server端请求数据时,缓存和数据库都不包含该数据,最终请求压力全部涌向数据库;
  • 发生原因:黑客利用漏洞伪造数据攻击或者内部业务bug造成大量重复请求不存在的数据时;

应用分析

        在实际应用中,选择多少哈希函数?分配多少位图空间?预期存储多少元素?如何控制误差?

        n--预期布隆过滤器中的元素个数;
        p--假阳率,在0-1之间 0.000000;
        m--位图所占空间;
        k--hash函数的个数;

        公式如下:
        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));

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值