海量数据去重的hash
1 背景使用word文档时word如何判断某个单词是否拼写正确网络爬虫程序怎么让它不去爬相同的url页面垃圾邮件过滤算法如何设计公安办案时如何判断某嫌疑人是否在网逃名单中缓存穿透问题如何解决平衡二叉树增删改查时间复杂度为 O(logn)平衡的目的是增删改后保证下次搜索能稳定排除一半的数据O(logn)的直观理解100万个节点最多比较20次10亿个节点最多比较 30次因此平衡二叉树的有序性是通过比较保证的通过每次排除一半的元素达到快速索引的目的2 散列表hash表而散列表则是通过key进行一定的处理哈希函数处理对数组长度取余后在对应的数组的索引位置存储。根据 key 计算 key 在表中的位置的数据结构是 key 和其所在存储地址的映射关系注意散列表的节点中 kv 是存储在一起的struct node { void *key; void *val; struct node *next; };2.1 hash函数映射函数 Hash(key)addrhash 函数可能会把两个或两个以上的不同 key 映射到同一地址这种情况称之为冲突或者hash 碰撞hash函数的选择计算速度快强随机分布等概率、均匀地分布在整个地址空间murmurhash1murmurhash2使用最多murmurhash3siphash redis6.0 当中使用rust 等大多数语言选用的 hash 算法来实现 hashmapcityhash 都具备强随机分布性测试地址如下https://github.com/aappleby/smhashersiphash 主要解决字符串接近的强随机分布性负载因子数组存储元素的个数 / 数组1长度用来形容散列表的存储密度负载因子越小冲突概率越小负载因子越大冲突概率越大2.2 冲突处理链表法引用链表来处理哈希冲突也就是将冲突元素用链表链接起来这也是常用的处理冲突的方式但是可能出现一种极端情况冲突元素比较多该冲突链表过长这个时候可以将这个链表转换为红黑树、最小堆由原来链表时间复杂度O(n)转 换为红黑树O(logn)时间复杂度那么判断该链表过长的依据是多少可以采用超过 256经验值个节点的时候将链表结构转换为红黑树或堆结构java hashmap开放寻址法将所有的元素都存放在哈希表的数组中不使用额外的数据结构一般使用线性探查的思路解决当插入新元素的时使用哈希函数在哈希表中定位元素位置检查数组中该槽位索引是否存在元素。如果该槽位为空则插入否则3在 2 检测的槽位索引上加一定步长接着检查2 加一定步长 分为以下几种i1,i2,i3,i4, ... ,ini-1^2 ,i2^2 ,i-3^2 ,14^2, ... 这两种都会导致同类 hash 聚集也就是近似值它的hash值也近似那么它的数组槽位也靠近形成 hash 聚集第一种同类聚集冲突在前第二种只是将聚集冲突延后另外还可以使用双重哈希来解决上面出现的hash聚集现象下面要讲的布隆过滤器也是使用双重哈希的方式解决hash聚集的现象在.net HashTable类的hash函数Hk定义如下 Hk(key) [GetHash(key) k * (1 (((GetHash(key) 5) 1) %(hashsize – 1)))] % hashsize 在此 (1 (((GetHash(key) 5) 1) %(hashsize – 1))) 与 hashsize互为素数两数互为素数表示两者没有共同的质因⼦ 执⾏了 hashsize 次探查后哈希表中的每⼀个位置都有且只有⼀次被访问到也就是说对于给定的 key对哈希表中的同⼀位置不会同时使⽤Hi 和 Hj2.3 stl中实现的散列表结构在 STL 中 unordered_map、unordered_set、 unordered_multimap、unordered_multiset 四兄弟底层实现都是散列表stl实现的散列表对原始的散列表进行了优化如上图所示。原因是stl需要对迭代器进行封装即需要方便寻找某个节点所在的位置。所以有一个_M_before_begin的节点作为头节点将所有节点串成一个链表的结构。而数值中的索引指向的不是所在所以位置的第一个节点而是指向上一个节点所存储索引位置的最后一个节点。插入节点时类似一种头插法的感觉。3 布隆过滤器3.1 背景上面所讲的数据结构如红黑树、散列表、B树和B树都是采用的存储k和v数据。但是实际上有时候我们并不需要知道key具体对应的value的值我们只需要知道对应的key是否在某个容器中。那么这时候就可以使用布隆过滤器布隆过滤器是一种概率型数据结构它的特点是高效地插入和查询能确定某个字符串一定不存在或者可能存在布隆过滤器不存储具体数据所以占用空间小查询结果存在误差但是误差可控同时不支持删除操作例如我们需要在mysql数据库中插叙某个key对应的值直接查询需要经过网络交互和查找过程我们可以先在服务器部署一个布隆过滤器先判断是否存在于mysql中再进行查询。3.2 构成如上图所示我们可以采用byte buf[8]数据来表示64bit的位图1byte 8bit然后通过对key进行hash计算出一个值映射到位图中在对应索引位置中置为1。3.3 原理当一个元素加入位图时通过 k 个 hash 函数将这个元素映射到位图的 k 个点并把它们置为 1当检索时再通过 k 个 hash 函数运算检测位图的 k 个点是否都为 1如果有不为 1 的点那么认为该 key 不存在如果全部为 1则可能存在 为什么不支持删除操作在位图中每个槽位只有两种状态0 或者 1一个槽位被设置为 1 状态但不确定它被设置了多少次也就是不知道 被多少个 key 哈希映射而来以及是被具体哪个 hash 函数映射而来只要一个索引位为0就一定不存在如果都为1是否一定存在不一定可控的假阳率3.4 应用分析在实际应用中该选择多少个 hash 函数要分配多少空间的位图预期存储多少元素如何控制误差n -- 预期布隆过滤器中元素的个数如上图 只有str1和str2 两个元素 那么 n2 p -- 假阳率在0-1之间 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));Bloom filter calculator可以使用这个网址通过n和p计算对应的m和k的值上图引申出一个面试题在很多的hash函数中经常出现‘31’这个数字为什么原因可以通过上面这个图看出来其实时一个经验值当khash函数个数为31时假阳率或者冲突概率最低。那k个hash函数如何做到几十个hash函数呢选择一个 hash 函数通过给 hash 传递不同的种子偏移值采用线性探寻的方式构造多个 hash 函数#define MIX_UINT64(v) ((uint32_t)((v32)^(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) // k 是hash函数的个数 { Pos[i] (hash1 i*hash2) % m; // m 是位图的⼤⼩ }3.5 应用场景布隆过滤器通常用于判断某个 key 一定不存在的场景同时允许判断存在时有误差的情况常见处理场景① 缓存穿透的解决② 热 key 限流描述缓存场景为了减轻数据库mysql的访问压力在server 端与数据库mysql之间加入缓存redis用来存储热点数据描述缓存穿透server端请求数据时缓存和数据库都不包含该数据最终请求压力全部涌向数据库数据请求步骤如图中 2 所示发生原因黑客利用漏洞伪造数据攻击或者内部业务 bug 造成大量重复请求不存在的数据解决方案如图中 3 所示拓展知识缓存击穿 vs 缓存穿透 vs 缓存雪崩缓存穿透查询不存在的数据缓存和数据库均无记录恶意攻击。缓存雪崩大量缓存同时失效导致请求批量击穿到数据库。缓存击穿单个热点数据失效引发集中式高并发请求。某个热点数据在缓存过期或失效的瞬间大量并发请求直接穿透缓存层直接访问数据库对应解决方案缓存穿透可以使用布隆过滤器或者缓存空对象的方式解决。缓存雪崩缓存数据过期时间分散在设置缓存过期时间时增加随机值如base_time random_delta避免同时失效。多级缓存架构使用本地缓存如 Guava Cache作为一级缓存Redis 作为二级缓存分散压力。热点数据永不过期对极热点数据设置永不过期通过异步线程主动更新。限流与降级使用熔断器如 Hystrix限制并发请求量或直接返回默认值缓存击穿使用互斥锁在缓存失效时只允许一个线程去重建缓存其他线程等待实现过程请求发现缓存未命中时尝试获取分布式锁如 Redis 的SETNX。获取锁成功的线程查询数据库并重建缓存。其他线程等待锁释放后直接从缓存读取数据。Q在2GB 内存限制下从20 亿个整数中找到出现次数最多的数4 分布式一致性hash4.1 背景分布式一致性hash解决的是多个节点分布式缓存扩容的场景比如之前所学的redis的cluster集群一样。数据库的数据不会存储在一个节点中而是采用主从节点进行存储。如上图所示一个server端和三个redis端的节点三个节点对应着不同的机器。首先在server端对key进行运算确定存储到哪个节点中进行分布式的存储。但是当增加一个节点后就会有一个问题那么我们hash算法就会发生改变。原来对3取余就会变成对4取余。那么就会出现缓存失效的问题即扩容后算法改变后原来存储的某些索引再次查询时就找不到了。于是就引出了分布式一致性hash的解决方法先固定算法。分布式一致性 hash 算法将哈希空间组织成一个虚拟的圆环圆环的大小是2^32算法为hash(ip) %2^32最终会得到一个 [0,2^32-1 ] 之间的一个无符号整型这个整数代表服务器的编号多个服务器都通过这种方式在 hash 环上映射一个点来标识该服务器的位置当用户操作某个 key通过同样的算法生成一个值沿环顺时针定位某个服务器那么该 key 就在该服务器中;但是此时如果进行扩容仍然会出现缓存失效的问题如下图所示即原来用户2的数据时存储在服务器2中的扩容后我们查询时会在服务器3进行查询很明显是不可能查询到数据的因此出现缓存失效。但是这个缓存失效时小部分的缓存失效只是在用户2和服务器3之间的数据失效只需要将这一部分的数据进行迁移即可。4.2 hash偏移我们知道hash算法的强随机分布性的当样本数过少的时候就有可能出现一个问题如下图所示服务器的节点可能聚集在某个位置不能保证服务器节点均匀分布在哈希环上分布不均匀造成请求访问不均匀服务器承受的压力不均匀hash偏移问题本质就是样本数过少的问题为了解决哈希偏移的问题增加了虚拟节点的概念理论上哈希环上节点数越多数据分布越均衡为每个服务节点计算多个哈希节点虚拟节点通常做法是hash(IP:PORT:seqno) %2^32即可以在每个ip和端口之后再添加一个序列号的方式从而增加节点而存储的时候只需要截取前面的ip和端口即可确定对应存储的节点而且这种密集存储可以减少hash迁移的数据量。

相关新闻

社区贡献指南:如何为ESP8266 FastLED WebServer项目提交代码和文档

社区贡献指南:如何为ESP8266 FastLED WebServer项目提交代码和文档

社区贡献指南:如何为ESP8266 FastLED WebServer项目提交代码和文档 【免费下载链接】esp8266-fastled-webserver 项目地址: https://gitcode.com/gh_mirrors/es/esp8266-fastled-webserver ESP8266 FastLED WebServer是一个基于ESP8266开发板的开源项目&…

2026/7/21 11:48:33阅读更多 →
终极指南:SideJITServer为iOS 17+设备开启无线JIT编译的完整解决方案

终极指南:SideJITServer为iOS 17+设备开启无线JIT编译的完整解决方案

终极指南:SideJITServer为iOS 17设备开启无线JIT编译的完整解决方案 【免费下载链接】SideJITServer A JIT enabler for iOS 17 with a Windows/macOS computer on the same WiFi! 项目地址: https://gitcode.com/gh_mirrors/si/SideJITServer 在iOS 17及更高…

2026/7/21 5:08:10阅读更多 →
独角数卡自动化售货系统:构建高可用数字商品交易平台的技术实现方案

独角数卡自动化售货系统:构建高可用数字商品交易平台的技术实现方案

独角数卡自动化售货系统:构建高可用数字商品交易平台的技术实现方案 【免费下载链接】dujiaoka 🦄独角数卡(自动售货系统)-开源站长自动化售货解决方案、高效、稳定、快速!🚀🚀🎉🎉 项目地址:…

2026/7/21 11:56:14阅读更多 →
HarmonyOS 手写笔适配实战:压感轨迹、笔锋渲染、撤销重做和低延迟保存

HarmonyOS 手写笔适配实战:压感轨迹、笔锋渲染、撤销重做和低延迟保存

HarmonyOS 手写笔适配实战:压感轨迹、笔锋渲染、撤销重做和低延迟保存 手写笔体验好不好,用户通常几秒钟就能判断出来:落笔有没有延迟,快速划线会不会断,压感有没有层次,撤销是不是按一整笔撤回&#xff0c…

2026/7/21 16:35:49阅读更多 →
终极指南:如何用Universal Android Debloater轻松清理安卓手机预装应用

终极指南:如何用Universal Android Debloater轻松清理安卓手机预装应用

终极指南:如何用Universal Android Debloater轻松清理安卓手机预装应用 【免费下载链接】universal-android-debloater Cross-platform GUI written in Rust using ADB to debloat non-rooted android devices. Improve your privacy, the security and battery lif…

2026/7/21 16:35:49阅读更多 →
[具身智能-609]:LPC1768(Cortex‑M3)完整替代 Keil MDK 的所有 IDE 方案

[具身智能-609]:LPC1768(Cortex‑M3)完整替代 Keil MDK 的所有 IDE 方案

按 原厂免费最优、国产一体化免费、VS Code 开源组合、在线网页 IDE、付费商业 IDE 五大类整理,全部原生支持 LPC1768,规避 Keil 盗版法律风险。一、NXP 原厂免费 IDE(企业量产首选,迁移成本最低)1. MCUXpresso IDE&am…

2026/7/21 16:35:49阅读更多 →
HarmonyOS 鸿蒙电脑适配实战:窗口菜单、拖拽文件、快捷键和多窗口工作流

HarmonyOS 鸿蒙电脑适配实战:窗口菜单、拖拽文件、快捷键和多窗口工作流

HarmonyOS 鸿蒙电脑适配实战:窗口菜单、拖拽文件、快捷键和多窗口工作流 手机应用搬到鸿蒙电脑上,最常见的问题不是页面打不开,而是“能用但不顺手”:按钮还像手机一样挤在底部,文件只能点选择器不能拖进来&#xff0c…

2026/7/21 16:35:49阅读更多 →
泰坦之旅装备管理革命:TQVaultAE如何重新定义ARPG物品存储范式

泰坦之旅装备管理革命:TQVaultAE如何重新定义ARPG物品存储范式

泰坦之旅装备管理革命:TQVaultAE如何重新定义ARPG物品存储范式 【免费下载链接】TQVaultAE Extra bank space for Titan Quest Anniversary Edition 项目地址: https://gitcode.com/gh_mirrors/tq/TQVaultAE 你是否曾在《泰坦之旅》的史诗冒险中,…

2026/7/21 16:35:49阅读更多 →
3步打造你的专属哔咔漫画图书馆:多线程下载器完全指南 [特殊字符]

3步打造你的专属哔咔漫画图书馆:多线程下载器完全指南 [特殊字符]

3步打造你的专属哔咔漫画图书馆:多线程下载器完全指南 😊 还在为哔咔漫画的在线阅读限制而烦恼吗?哔咔漫画下载器让你轻松收藏心爱的漫画,打造个人离线图书馆!这款多线程下载器不仅下载速度快如闪电,还自带…

2026/7/21 16:33:49阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/21 0:51:49阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/21 0:51:49阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/21 0:51:49阅读更多 →
Windows+macOS 通用 OpenClaw 部署流程,内置依赖一键启动智能桌面助手

Windows+macOS 通用 OpenClaw 部署流程,内置依赖一键启动智能桌面助手

📌教程适配:OpenClaw v2.7.9 | 兼容 Windows10/11、macOS 双系统 📖前言 当下各类本地 AI 工具层出不穷,多数产品仅能完成文字问答交互,很难直接操控电脑执行实际操作。OpenClaw,业内常称小龙虾 AI&#…

2026/7/21 0:01:46阅读更多 →
Codex 接入后 Bug 反增?复盘从个人演示到团队协作的“流程陷阱”

Codex 接入后 Bug 反增?复盘从个人演示到团队协作的“流程陷阱”

聊《一次Codex项目复盘,问题最后出在流程而不是模型》之前,先说一句实在的:别急着背概念,先看它在真实项目里到底解决什么问题。摘要先把这篇文章的目标说清楚:看完之后,你应该能判断这件事值不值得做&…

2026/7/21 0:01:46阅读更多 →
手把手搓一个五子棋游戏,零代码也能当“游戏开发者”

手把手搓一个五子棋游戏,零代码也能当“游戏开发者”

大家好,还是我。前几期带大家做了心情日记本和可视化大屏,后台有朋友留言:“能不能教点好玩的?我想做游戏,但一行代码都不会。”行,这期就安排。今天的目标:从零做一个五子棋游戏。 带AI对战、三…

2026/7/21 0:03:46阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/20 22:51:39阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/20 18:51:18阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/20 18:51:18阅读更多 →