位图与布隆过滤器 —— 海量数据处理

🌈 个人主页:Zfox_
🔥 系列专栏:C++从入门到精通

目录
- 🚀 位图
- 一: 🔥 位图概念
- 二: 🔥 位图的实现思路及代码实现
- 三: 🔥 位图的应用
- 四: 🔥 STL中的 bitset
- 🚀 布隆过滤器
- 一: 🔥 布隆过滤器提出
- 二: 🔥 布隆过滤器概念
- 三: 🔥 布隆过滤器的误判率推导
- 四: 🔥 布隆过滤器的实现
- 五: 🔥 布隆过滤器的删除
- 六: 🔥 布隆过滤器的应用
- 🚀 哈希切分
- 🔥 应用一
- 🔥 应用二
- 🚀 共勉
🚀 位图
一: 🔥 位图概念
🥝 所谓位图,就是用每一位来存放某种状态,适用于海量数据,数据无重复的场景。通常是用来判断某个数据存不存在的。
💢 我们来看一道十分经典的面试题
给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中。【腾讯】
遍历,时间复杂度O(N)
排序(O(NlogN)),利用二分查找: logN
位图解决
数据是否在给定的整形数据中,结果是在或者不在,刚好是两种状态,那么可以使用一个二进制比特位来代表数据是否存在的信息,如果二进制比特位为1,代表存在,为0代表不存在。

- 位图的解法差不多是这道题的最优解,只需要将所有数据读入后将对应位置置1,然后再查找那个数据所储的位置是否为1即可。
二: 🔥 位图的实现思路及代码实现
🥝 位图
的实现思路:
🎯 为了方便实现,
位图的底层可以使用一个vector
。而开空间并不根据数据的个数来开,而是根据数据的范围来开
(如果开的空间不够,可能有位置无法映射到)。并且一个整型具有32个字节,所以如果我们要存N个数据,就只需要开N / 32 + 1的空间
即可(+1是为了防止数据小于32和向上取整)。
🎯 当要操作一个数据时,先将其除以32来判断它应该处于数组中哪一个整型中。再对其%32,来判断它位于这个整型中的哪一个位上,此时再进行对应的位运算即可。
💢 代码实现及说明如下:
template<size_t N>
class bitset
{
public:bitset(){_bs.resize(N / 32 + 1);}// x映射的位标记成1void set(size_t x){size_t i = x / 32;size_t j = x % 32;_bs[i] |= (1 << j);}// x映射的位标记成0void reset(size_t x){size_t i = x / 32;size_t j = x % 32;_bs[i] &= (~(1 << j));}// x映射的位是1返回真// x映射的位是0返回假bool test(size_t x){size_t i = x / 32;size_t j = x % 32;return _bs[i] & (1 << j);}private:std::vector<int> _bs;
};
三: 🔥 位图的应用
- 💢 给定100亿个int,1G内存,设计算法找到只出现一次的整数。
首先,1G内存大约有80亿的bit位,而100亿个int,int 最多能表示大约42亿9千万个数,也就是说100亿的数据一半以上都是重复的;我们只用43亿个bit位就可以解决该问题,所以这里使用1G空间完全可以解决该问题。
这是一个KV统计搜索模型,我们可以使用两个位图来解决,用两个位图中对应位置的值来表示这个整数的出现情况:
0次 —> 00
1次 —> 01
2次及以上 —> 10
- 🥝 我们可以复用上面我们自己实现的
bitset
去重新封装一个twobitset
代码实现及说明如下:
template<size_t N>
class twobitset
{
public:void set(size_t x){bool bit1 = _bs1.test(x);bool bit2 = _bs2.test(x);if (!bit1 && !bit2) // 00->01{_bs2.set(x);}else if (!bit1 && bit2) // 01->10{_bs1.set(x);_bs2.reset(x);}else if (bit1 && !bit2) // 10->11{_bs1.set(x);_bs2.set(x);}}// 返回0 出现0次数// 返回1 出现1次数// 返回2 出现2次数// 返回3 出现2次及以上int get_count(size_t x){bool bit1 = _bs1.test(x);bool bit2 = _bs2.test(x);if (!bit1 && !bit2){return 0;}else if (!bit1 && bit2){return 1;}else if (bit1 && !bit2){return 2;}else{return 3;}}private:bitset<N> _bs1;bitset<N> _bs2;
};
🍊 这样我们就通过两个位图巧妙的解决了这个问题。
四: 🔥 STL中的 bitset
🎯 bitset官方文档
🍊 stl中的 bitset
底层是一个静态数组,是在栈上开辟的空间,所以需要注意栈溢出
的风险。
🍐 位图
的优缺点:
优点:增删改查快、节省空间
缺点:只适用于整形
🚀 布隆过滤器
一: 🔥 布隆过滤器提出
🍊 我们在使用新闻客户端看新闻时,它会给我们不停地推荐新的内容,它每次推荐时要去重,去掉那些已经看过的内容。问题来了,新闻客户端推荐系统如何实现推送去重的? 用服务器记录了用户看过的所有历史记录,当推荐系统推荐新闻时会从每个用户的历史记录里进行筛选,过滤掉那些已经存在的记录。 如何快速查找呢?
1. 用哈希表存储用户记录,缺点:浪费空间。2. 用位图存储用户记录,缺点:位图一般只能处理整形,如果内容编号是字符串,就无法处理了。
3. 将哈希与位图结合,即布隆过滤器。
二: 🔥 布隆过滤器概念
🍐 布隆过滤器
是由布隆(Burton Howard Bloom)在1970年提出的 一种紧凑型的、比较巧妙的概率型数据结构
,特点是高效地插入和查询,可以用来告诉你 “某样东西一定不存在或者可能存在”,它是用多个哈希函数将一个数据映射到位图结构中。此种方式 不仅可以提升查询效率
,也可以节省大量的内存空间
。
🍐
布隆过滤器
的思路就是把key先映射转成哈希整型值,再映射一个位,如果只映射一个位的话,冲突率会比较多,所以可以通过多个哈希函数
映射多个位,降低冲突率。 布隆过滤器这里跟哈希表不一样,它无法解决哈希冲突的,因为他压根就不存储这个值,只标记映射的位。它的思路是尽可能降低哈希冲突。判断一个值key在是不准确的,判断一个值key不在是准确的。
三: 🔥 布隆过滤器的误判率推导


如果大家还想更深了解可以参考下面这篇文章
💢 如何选择哈希函数个数和布隆过滤器长度 一文中,对这个问题做了详细的研究和论证。
四: 🔥 布隆过滤器的实现
哈希函数
🍐 首先需要写几个哈希函数来将字符串转换成整形,各种字符串Hash函数一文中,介绍了多种字符串转换成整数的哈希函数,并且根据冲突概率进行了性能比较,有兴趣的朋友可以自行研究一下。
//下面三个字符串转换成整形的仿函数
struct HashFuncBKDR
{// @detail 本 算法由于在Brian Kernighan与Dennis Ritchie的《The CProgramming Language》// 一书被展示而得 名,是一种简单快捷的hash算法,也是Java目前采用的字符串的Hash算法累乘因子为31。size_t operator()(const std::string& s){size_t hash = 0;for (auto ch : s){hash *= 31;hash += ch;}return hash;}
};struct HashFuncAP
{// 由Arash Partow发明的一种hash算法。 size_t operator()(const std::string& s){size_t hash = 0;for (size_t i = 0; i < s.size(); i++){if ((i & 1) == 0) // 偶数位字符{hash ^= ((hash << 7) ^ (s[i]) ^ (hash >> 3));}else // 奇数位字符{hash ^= (~((hash << 11) ^ (s[i]) ^ (hash >> 5)));}}return hash;}
};struct HashFuncDJB
{// 由Daniel J. Bernstein教授发明的一种hash算法。 size_t operator()(const std::string& s){size_t hash = 5381;for (auto ch : s){hash = hash * 33 ^ ch;}return hash;}
};
🍊 布隆过滤器框架实现
template<size_t N, //最多存储的数据个数。size_t X = 5, class K = std::string, class Hash1 = HashFuncBKDR, class Hash2 = HashFuncAP,class Hash3 = HashFuncDJB>class BloomFilter
{
public://标记一个字符串是否存在void Set(const K& key){// 将一个字符串转换成三个整型size_t hash1 = Hash1()(key) % M;size_t hash2 = Hash2()(key) % M;size_t hash3 = Hash3()(key) % M;//cout << hash1 <<" "<< hash2 <<" "<< hash3 << endl;// 进行三次映射_bs.set(hash1);_bs.set(hash2);_bs.set(hash3);}// 判断每个比特位时,判断它不存在,注:不要判断它存在,因为不存在是准确的,存在是不准确的。bool Test(const K& key){size_t hash1 = Hash1()(key) % M;if (!_bs.test(hash1)){return false;}size_t hash2 = Hash2()(key) % M;if (!_bs.test(hash2)){return false;}size_t hash3 = Hash3()(key) % M;if (!_bs.test(hash3)){return false;}return true; // 可能存在误判}// 获取公式计算出的误判率double getFalseProbability(){double p = pow((1.0 - pow(2.71, -3.0 / X)), 3.0);return p;}private:static const size_t M = N * X;island::bitset<M> _bs;
};
五: 🔥 布隆过滤器的删除
- 🎯 布隆过滤器不能直接支持删除工作,因为在删除一个元素时,可能会影响其他元素。
“猪八戒” 和 “孙悟空” 映射的比特位都有第4个比特位。删除上图中 “猪八戒” 元素,如果直接将该元素所对应的二进制比特位置0,“孙悟空” 的元素也被删除了,因为这两个元素在多个哈希函数计算出的比特位上刚好有重叠。
一种支持删除的方法:将布隆过滤器中的每个比特位扩展成一个小的计数器,插入元素时给k个计数器(k个哈希函数计算出的哈希地址)加一,删除元素时,给k个计数器减一,通过多占用几倍存储空间的代价来增加删除操作。
🇺🇳 缺陷:
1. 无法确认元素是否真正在布隆过滤器中
2. 如果采用计数方式删除,存在计数回绕
六: 🔥 布隆过滤器的应用
首先我们分析⼀下布隆过滤器的优缺点:
💢 优点
1. 增加和查询元素的时间复杂度为:O(K), (K为哈希函数的个数,一般比较小),与数据量大小无关。
2. 哈希函数相互之间没有关系,方便硬件并行运算。
3. 布隆过滤器不需要存储元素本身,在某些对保密要求比较严格的场合有很大优势。
5. 在能够承受一定的误判时,布隆过滤器比其他数据结构有这很大的空间优势。
5. 数据量很大时,布隆过滤器可以表示全集,其他数据结构不能。
6. 使用同一组散列函数的布隆过滤器可以进行交、并、差运算。
💢 缺点
1. 有
误判率
,即存在假阳性(False Position)
,即不能准确判断元素是否在集合中 (补救方法:再建立一个白名单,存储可能会误判的数据)。
2. 不能获取元素本身。
3. 一般情况下不能从布隆过滤器中删除元素
。
4. 如果采用计数方式删除,可能会存在计数回绕
问题。
布隆过滤器在实际中的⼀些应用:
- 爬虫系统URL去重
在爬虫系统中,为了避免重复爬取相同的URL,可以用布隆过滤器来进行URL去重。爬取到的URL可以通过布隆过滤器进行判断,已经存在的URL则可以直接忽略,避免重复的网络请求和数据处理。
- 垃圾邮件过滤
在垃圾邮件过滤系统中,布隆过滤器可以用来判断邮件是否是垃圾邮件。系统可以将已知的垃圾邮件 的特征信息存储在布隆过滤器中,当新的邮件到达时,可以通过布隆过滤器快速判断是否为垃圾邮件,从而提高过滤的效率。
- 预防缓存穿透
在分布式缓存系统中,布隆过滤器可以用来解决缓存穿透的问题。缓存穿透是指恶意用户请求⼀个不存在的数据,导致请求直接访问数据库,造成数据库压力过大。布隆过滤器可以先判断请求的数据是 否存在于布隆过滤器中,如果不存在,直接返回不存在,避免对数据库的无效查询。
- 对数据库查询提效
在数据库中,布隆过滤器可以用来加速查询操作。例如:⼀个app要快速判断⼀个电话号码是否注册过,可以使⽤布隆过滤器来判断⼀个用户电话号码是否存在于表中,如果不存在,可以直接返回不存 在,避免对数据库进行无用的查询操作。如果在,再去数据库查询进行二次确认。
🚀 哈希切分
我们可以用哈希切分对海量数据处理问题
🔥 应用一
给两个⽂件,分别有100亿个query,我们只有1G内存,如何找到两个⽂件交集?
分析:假设平均每个query字符串50byte,100亿个query就是5000亿byte,约等于500G(1G约等于 10亿多Byte)
哈希表 / 红⿊树等数据结构肯定是⽆能为⼒的。
- 解决方案1:
这个⾸先可以⽤布隆过滤器解决,⼀个文件中的query放进布隆过滤器,另⼀个文件依次查找,在的就是交集,问题就是到交集不够准确,因为在的值可能是误判的,但是交集⼀定被找到了。
- 解决方案2:
哈希切分
,首先内存的访问速度远大于硬盘,大文件放到内存搞不定,那么我们可以考虑切分为小文件,再放进内存处理。- 但是不要平均切分,因为平均切分以后,每个小文件都需要依次暴力处理,效率还是太低了。
- 可以利⽤哈希切分,依次读取文件中query,i=HashFunc(query)%N,N为准备切分多少分小文件,N取决于切成多少份,内存能放下,query放进第i号小文件,这样A和B中相同的query算出的 hash值i是⼀样的,相同的query就进⼊的编号相同的小文件就可以编号相同的文件直接找交集,不⽤交叉找,效率就提升了。
- 本质是相同的query在哈希切分过程中,⼀定进⼊的同⼀个小文件Ai和Bi,不可能出现A中的的 query进⼊Ai,但是B中的相同query进⼊了和Bj的情况,所以对Ai和Bi进⾏求交集即可,不需要Ai 和Bj求交集。(本段表述中i和j是不同的整数)
- 哈希切分的问题就是每个小文件不是均匀切分的,可能会导致某个小文件很⼤内存放不下。我们细细分析⼀下某个小文件很大有两种情况:
- 这个小文件中大部分是同⼀个query。
- 这个小文件是 有很多的不同query构成,本质是这些query冲突了。
针对情况1,其实放到内存的set中是可以放下的,因为set是去重的。针对情况2,需要换个哈希函数继续⼆次哈希切分。所以本体我们遇到大于1G小文件,可以继续读到set中找交集,若set insert时抛出了异常(set插⼊数据抛异常只可能是 申请内存失败了,不会有其他情况),那么就说明内存放不下是情况2,换个哈希函数进⾏二次哈希切分后再对应找交集。
🔥 应用二
给一个超过100G大小的log file, log中存着IP地址, 设计算法找到出现次数最多的IP地址?
本题的思路跟上题完全类似,依次读取文件A中query, i = HashFunc(query) % 500,query 放进 Ai 号小文件,然后依次⽤ map 对每个A小文件统计 ip 次数,同时求出现次数最多的 ip或者topk ip。本质是相同的 ip 在哈希切分过程中,⼀定进⼊的同⼀个小文件Ai,不可能出现同⼀个ip进⼊ Ai 和 Aj 的情况,所以对Ai进行统计次数就是准确的ip次数。

🚀 共勉
以上就是我对 位图与布隆过滤器 —— 海量数据处理
的理解,觉得这篇博客对你有帮助的,可以点赞收藏关注支持一波~😉
相关文章:

位图与布隆过滤器 —— 海量数据处理
🌈 个人主页:Zfox_ 🔥 系列专栏:C从入门到精通 目录 🚀 位图 一: 🔥 位图概念 二: 🔥 位图的实现思路及代码实现三: 🔥 位图的应用四:…...

二:《Python基础语法汇总》— 条件判断与循环结构
一:条件判断 1.程序执行的三大流程: 顺序流程:无缩进代码,从上往下依次执行 分支流程:选择性执行某块代码,或跳过某行代码去执行,与缩进(TAB)有关 循环流程&…...

【威锋网-注册安全分析报告-无验证方式导致安全隐患】
前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 1. 暴力破解密码,造成用户信息泄露 2. 短信盗刷的安全问题,影响业务及导致用户投诉 3. 带来经济损失,尤其是后付费客户,风险巨大,造…...

01_React简介、基础入门
React 简介、基础入门 一、React 简介1、是什么?2、谁开发的?3、为什么要学?4、React 的特点5、学习 React 之前你要掌握的 Javascript 基础知识 二、React 入门1、相关 js 库2、Hello React 入门小例子---React16.8.0 版本3、为什么不用 js …...

【Java 内存区域】
Java内存区域 JDK1.7 VS JDK1.8堆 (Heap)方法区 (Method Area)String 常量池 (String Pool)运行时常量池 (Runtime Constant Pool)虚拟机栈 (JVM Stack)局部变量表操作数栈动态链接方法返回信息 本地方法栈 (Native Method Stack)程序计数器 (Program Counter Register)元空间 …...

你是如何克服编程学习中的挫折感的?
一:学习之路 在编程学习的过程中,挫折和挑战是不可避免的。面对这些困难,我个人的一些经验和方法如下,或许能为你提供一些启示: 1. 学会分解问题 当遇到复杂的算法或者Bug时,我会将问题分解成更小的部分。…...

【AI应用实战】灵办AI插件集成详细指南
一、写在前面 随着AI技术的日新月异,大型模型应用如雨后春笋般涌现,从ChatGPT到文心一言,再到讯飞星火,无一不彰显着智能科技的无限潜力。而在这股浪潮中,我们欣喜地发现,一些创新的浏览器插件正悄然兴起&a…...

MySQL数据库连接超时问题排查报告
1、问题描述 边端设备访问云端过程中有概率出现MySQL数据库连接超时报错,具体报错代码如下: [2024-08-13 13:47:44,036] ERROR in app: Exception on /est-tasks/start [POST] Traceback (most recent call last): File "/usr/local/lib/python3.1…...

代码随想录第三天 | 链表
文章目录 链表理论知识定义链表删除链表 Leetcode203 移除链表元素代码实现 Leetcode707 设计链表代码实现复杂度分析错误点 Leetcode206 反转链表新建链表双指针法 链表理论知识 链接: https://programmercarl.com/%E9%93%BE%E8%A1%A8%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.h…...

Python编码系列—Python数据可视化:Matplotlib与Seaborn的实战应用
🌟🌟 欢迎来到我的技术小筑,一个专为技术探索者打造的交流空间。在这里,我们不仅分享代码的智慧,还探讨技术的深度与广度。无论您是资深开发者还是技术新手,这里都有一片属于您的天空。让我们在知识的海洋中…...

putty中修改默认窗口大小和字体、字号
在WinSCP中调用putty,发现默认窗口太小,字号也很小,非常不友好。现在显示器都是1080p起步,所以很有必要修改之。 以中文版v0.70为例,方法: 1. 点击左上角图标 ,选择下拉菜单中的“修改设置”&…...

Windows下网络编与ESP8266-WiFi通信(win32-API)
一、前言 络编程是指编写程序使不同计算机之间能够通过网络进行通信和数据交换。网络编程涉及使用网络协议和编程接口来建立、管理和终止网络上的数据通信。在这一领域中,TCP/IP协议族是核心组成部分,尤其TCP(传输控制协议)是面向…...

【Golang】golang安装一些依赖包时总是失败
Golang安装一些依赖包失败: 比如安装gin包:go get -u github.com/gin-gonic/gin 可能会报错:连接网络失败、超时等 这时可能需要修改go的环境配置,修改代理即可: go env -w GO111MO…...

ubuntu如何监控Xvfb虚拟显示器
在Ubuntu中监控Xvfb显示器主要涉及到使用VNC服务器来远程访问这个环境。以下是一些基本步骤: 安装Xvfb和相关工具: 使用apt安装Xvfb和x11vnc,x11vnc是一个VNC服务器,可以远程访问Xvfb创建的虚拟桌面环境。 sudo apt-get install xvfb sudo ap…...

小型需求管理软件盘点:8款功能强大的工具
本文介绍了以下8款工具:PingCode、Worktile、易得云、Ping、燃草、Gitee、Monday.com、Slack。 在现代企业管理中,需求管理一直是个让人头疼的问题,特别是对于小型企业来说,选择一款合适的需求管理软件往往比想象中更复杂。如果选…...

Labelme的安装与使用教程
文章目录 一、Labelme是什么?二、安装步骤1.新建虚拟环境2.安装Labelme3.Labelme的使用 三、json2yolo 一、Labelme是什么? Labelme是一个用于图像标注的开源工具,可以实现图像标注、语义分割、实例分割等。 本文记录一下labelme的安装与使…...

C#基础:数据库中使用Linq作分组处理(反射/直接分组)
目录 一、使用反射分组 二、不使用反射分组 三、调用示例 四、代码demo 一、使用反射分组 private static List<GroupList<T>> GetGroupList<T>(List<T> entities, string groupByProperty) {// 获取分组字段的类型var propertyInfo typeof(T).…...

Revite二次开发_使用WPF和WebView2制作一个访问网站的窗口
如果想在revit里打开网页,可以使用WebView2来实现,下面是一个代码示例。 也尝试过使用CefSharp,但由于Revit本身也使用了CefSharp,所以需要根据不同的Revit版本选择适合的CefSharp版本,比较麻烦,所以最好还…...

Java Spring Boot 连接数据库
要在Java Spring Boot应用程序中连接数据库,您需要遵循以下步骤: 1. 添加数据库依赖项:在您的Spring Boot项目中的pom.xml文件中添加数据库依赖项,例如MySQL或PostgreSQL等。例如,如果您要连接MySQL数据库,…...

Java面试八股之消息队列中推模式和拉模式分别有哪些使用场景
消息队列中推模式和拉模式分别有哪些使用场景 消息队列的推模式(Push)和拉模式(Pull)各有不同的使用场景和优缺点。下面我会详细介绍这两种模式及其适用场景: 推模式(Push) 特点:…...

springboot jar是如何启动的
我们先来看一个项目的打完包后的MANIFEST.MF文件: Manifest‐Version: 1.0 Implementation‐Title: spring‐learn Implementation‐Version: 0.0.1‐SNAPSHOT Start‐Class: com.tulingxueyuan.Application Spring‐Boot‐Classes: BOOT‐INF/classes/ Spring‐Bo…...

Android 12系统源码_屏幕设备(二)DisplayAdapter和DisplayDevice的创建
前言 在Android 12系统源码_屏幕设备(一)DisplayManagerService的启动这篇文章中我们具体分析了DisplayManagerService 的启动流程,本篇文章我们将在这个的基础上具体来分析下设备屏幕适配器的创建过程。 一、注册屏幕适配器 系统是在Disp…...

常用Mysql命令
前言 本文列举了一些常见的mysql操作 正文 一、连接和登录 MySQL 1. 使用命令行登录 MySQL 注意:需要将mysql的bin目录导入到环境变量中 mysql -u 用户名 -p示例: mysql -u root -p执行上述命令后,系统会提示输入密码,输入…...

IDEA Debug工具
一、Debug工具栏 自定义debug工具栏:先把debug程序运行起来->右击->配置 常用的工具: 二、DeBug常用图标详解 三、DeBug实践操作 常规Debug:略。 Stream Chain:处理流式语句 Reset Frame:重置方法入栈 …...

ARM64的汇编资源
最近在写一本ARM64的教材,所以在晚上查找了一下相关资源,都是免费开源的,不包括盗版书籍。 Exploring AArch64 assembler Roger Ferrer Ibez的博客文章,写在2016-2017年,内容简单充实,适合入门。 《ARM6…...

实验室安全分级分类管理系统在高校中的具体应用
盛元广通高校实验室安全分级分类管理系统的构建,旨在通过科学合理的管理手段,提高实验室的安全水平,保障师生的人身安全,防止实验事故的发生。这一系统通常包括实验室安全等级评估、分类管理、风险控制、安全教育与培训、应急响应…...

使用 prerenderRoutes 进行预渲染路由
title: 使用 prerenderRoutes 进行预渲染路由 date: 2024/8/20 updated: 2024/8/20 author: cmdragon excerpt: prerenderRoutes 函数是 Nuxt 3 中一个强大的工具,它能够帮助开发者优化页面加载速度和改善用户体验。通过使用 prerenderRoutes,你能够灵活地指定需要预渲染的…...

【深度解析】WRF-LES与PALM微尺度气象大涡模拟
查看原文>>>【深度解析】WRF-LES与PALM微尺度气象大涡模拟 针对微尺度气象的复杂性,大涡模拟(LES)提供了一种无可比拟的解决方案。微尺度气象学涉及对小范围内的大气过程进行精确模拟,这些过程往往与天气模式、地形影响和…...

redis事件机制
redis服务器是一个由事件驱动(死循环)的程序,它总共就干两件事: 文件事件:利用I/O复用机制,监听Socket等文件描述符发生的事件,如网络请求时间事件:定时触发的事件,负责完成redis内部定时任务&…...

【C++】模拟实现vector
可以把vector看作升级版的数组,可采用下标进行访问,非常高效,大小可动态改变,会自动扩容,数据存储在堆空间上。 VECROR 成员变量、函数及模板总览构造函数和析构函数无参构造函数构造n个元素大小的空间并初始化通过某个…...