Bootstrap

【高阶数据结构】布隆过滤器和分布式一致性hash

1. 前置知识

① 散列表

散列表,也叫哈希表,是一种能够通过给定的关键字的值直接访问到具体对应的值的一个数据结构

散列表用的是数组支持按照下标随机访问数据的特性,所以散列表其实就是数组的一种扩展

散列表有两种用法:一种是键值和值相同,称为集合;另一种是键值和值不同,称为映射

② Hash函数

Hash函数,也叫散列函数,是一种把任意长度的输入变换成固定长度的输出的函数,Hash函数的作用是通过关于键值的函数,将数据映射到内存存储中一个位置来访问

对于不同的输入可能会散列成相同的输出,导致无法从散列表来唯一确定输入值,这种情况称为Hash冲突

③ 为什么要选择Hash

hash的优点是计算速度快、检索效率非常高,可以一次到位,而且可以实现安全加密,具有强随机分布的特点

murmurhash1,murmurhash2,murmurhash3,siphash(redis6.0当中使⽤,rust等大多数语言选用的hash算法来实现hashmap,它主要解决字符串接近的强随机分布性),cityhash 都具备强随机分布性

Hash有很多的应用场景,如:存储商品、淘宝短链接、分布式session、用户注册、MySQL中的Memory存储引擎和自适应Hash等等

④ 负载因子

负载因子是哈希表中用来衡量哈希表的空/满程度的一个比值,它的值等于哈希表中的元素个数除以哈希表的大小

负载因子越大表示哈希表越满,则发生哈希冲突的可能性就越高,查询效率也就越低
负载因子越小,说明哈希表越空,浪费的空间就越多

因此要选择一个合适的负载因子,一边默认为0.75

⑤ 解决哈希冲突

  • 开放寻址法:从发生冲突的位置开始,按照一定的顺序,找到一个空闲的位置存放元素,这种方法需要控制哈希表的负载因子,避免过多的冲突和探测
  • 链地址法:也叫拉链法,每个哈希位置存放一个链表头指针,所有映射到该位置的元素都插入到链表中,这种方法需要额外的空间存储链表结点
  • 再哈希法:构造多个不同的哈希函数,在发生冲突时,使用另一个哈希函数计算新的地址,这种方法需要设计多个好的哈希函数,并且保证不会出现循环冲突
  • 建立公共溢出区:将哈希表分为基本表和溢出表,当基本表发生冲突时,将元素存入溢出表中,这种方法简化了对基本表的操作,但是增加了对溢出表的管理

2. 布隆过滤器介绍

布隆过滤器是一种高空间利用率的概率型数据结构,它由一个二进制向量(即位数组)和一系列随机映射函数(即哈希函数)组成

布隆过滤器可以用于判断一个元素是否可能存在于一个集合中,如果返回否,则该元素一定不存在;如果返回是,则该元素有一定概率存在

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

3. 布隆过滤器原理

在这里插入图片描述
当一个元素加入位图时,通过 k 个 hash 函数将这个元素映射到位图的 k 个点,并把它们置为 1;当检索时,再通过 k 个 hash 函数运算检测位图的 k 个点是否都为 1;如果有不为 1 的点,那么认为该 key 不存在;如果全部为 1,则可能存在。

为什么不支持删除操作:
在位图中每个槽位只有两种状态(0 或者 1),一个槽位被设置为 1 状态,但不确定它被设置了多少次,也就是不知道被多少个 key 哈希映射而来以及是被具体哪个 hash 函数映射而来

4. 布隆过滤器的应用场景

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

① 解决缓存穿透

缓存穿透是指有恶意请求查询不存在的数据,导致缓存和数据库都无法命中,从而给数据库造成压力的问题

解决方法是将所有可能存在的数据缓存放到布隆过滤器中,当用户请求一个数据时,先用布隆过滤器判断是否存在,如果不存在就直接返回,避免查询缓存和数据库

② 热key限流

热key限流是指对于一些访问频率很高的key,采取一些措施来减少对缓存或数据库的压力,比如设置过期时间、分布式锁、限流算法等

布隆过滤器可以用于热key限流的一个场景是,当有大量的请求查询一个不存在的key时,如果直接访问缓存或数据库,可能会造成缓存穿透或雪崩,这时候可以使用布隆过滤器来快速判断这个key是否存在,如果不存在就直接拒绝请求,从而减少无效的查询

③ 回答步骤

在这里插入图片描述

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

5 . 布隆过滤器应用分析

① 参数选择

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

公式如下:
n − − 预期布隆过滤器中元素的个数,如上图只有 s t r 1 和 s t r 2 两个元素那么 n = 2 p − − 假阳率,在 0 − 1 之间 0.000000 m − − 位图所占空间 k − − h a s h 函数的个数 n = c e i l ( m / ( − k / l o g ( 1 − e x p ( l o g ( p ) / k ) ) ) ) p = p o w ( 1 − e x p ( − k / ( m / n ) ) , k ) m = c e i

;