0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

分享一下关于Linux服务器开发中相关数据去重的做法

嵌入式开发AIoT 来源:嵌入式开发AIoT 2023-06-18 17:22 次阅读

1. 海量数据去重的Hash

1.1 背景

● 在使用word文档时,word如何判断某个单词是否拼写正确?

网络爬虫程序,怎么让它不去爬相同的url页面?

● 垃圾邮件(短信)过滤算法如何设计?

● 公安办案时,如何判断某嫌疑人是否在网逃名单中?

● 缓存穿透问题如何解决?

5467d778-0db5-11ee-962d-dac502259ad0.png

描述缓存场景,为了减轻落盘数据库(mysql)的访问压力,在server端与mysql之间加入一层缓冲数据层(用来存放热点数据);

缓存穿透发生的场景是server端向数据库请求数据时,缓存数据库(redis)和落盘数据库(mysql)都不包含该数据,数据请求压力全部涌向落盘数据库(mysql)。

数据请求步骤:如上图2的描述;

发送原因:黑客利用漏洞伪造数据攻击或者内部业务bug重复大量请求不存在的数据;

解决方法:如上图3的描述;

1.2 需求

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

1.3 set和map

c++标准库(STL)中的set和map结构都是采用红黑树实现的,它增删改查的时间复杂度是o(log2n );

图结构示例:

54873212-0db5-11ee-962d-dac502259ad0.png

对于严格平衡二叉搜索树(AVL),100w条数据组成的红黑树,只需要比较20次就能找到该值;对于10亿条数据只需要比较30次就能找到该数据;也就是查找次数跟树的高度是一致的;

对于红黑树来说平衡的黑节点高度,所以研究次数需要考虑树的高度差,最好情况某条树链路全是黑节点,假设此时高度为h1,最差情况某条树链路全是黑红节点间隔,那么此时树高度为2*h1;

在红黑树中每一个节点都存储key和val字段,key是用来做比较的字段;红黑树并没有要求key字段唯一,在set和map实现过程中限制了key字段唯一。我们来看nginx的红黑树实现:

//这个是截取nginx的红⿊树的实现,这段代码是insert操作中的⼀部分,执⾏完这个函数还
需要检测插⼊节点后是否平衡(主要是看他的⽗节点是否也是红⾊节点)
//调⽤ngx_rbtree_insert_value时,temp传的参数为红⿊树的根节点,node传的参数为
待插⼊的节点
voidngx_rbtree_insert_value(ngx_rbtree_node_t*temp,ngx_rbtree_node_t
*node,
{
ngx_rbtree_node_t**p;
for(;;){
p=(node->key< temp->key)?&temp->left:&temp->right;//这⾏很重要
if(*p==sentinel){
break;
}
temp=*p;
}
*p=node;
node->parent=temp;
node->left=sentinel;
node->right=sentinel;
ngx_rbt_red(node);
}
//不插⼊相同节点如果插⼊相同让它变成修改操作此时红⿊树当中就不会有相同的key了
定时器key时间戳
//如果我们插⼊key = 12,如上图红⿊树,12号节点应该在哪个位置?如果我们要实现插⼊存在
的节点变成修改操作,该怎么改上⾯的函数
voidngx_rbtree_insert_value_ex(ngx_rbtree_node_t*temp,ngx_rbtree_node_t
*node,
ngx_rbtree_node_t*sentinel)
{
ngx_rbtree_node_t**p;
for(;;){
//{-------------add-------------
if(node->key==temp->key){
temp->value=node->value;
return;
}
//}-------------add-------------
p=(node->key< temp->key)?&temp->left:&temp->right;//这⾏很重要
if(*p==sentinel){
break;
}
temp=*p;
}
*p=node;
node->parent=temp;
node->left=sentinel;
node->right=sentinel;
ngx_rbt_red(node);
}

另外set和map的关键区别是set不存储val字段;

优点:存储效率高,访问速度高效;

缺点:对于数据量大且查询字符串比较长且查询字符串相似时将会是噩梦;

1.4 unordered_map

c++标准库(STL)中的unordered_map是采⽤hashtable实现的;

构成:数组+hash函数;

它是将字符串通过hash函数⽣成⼀个整数再映射到数组当中;它增删改查的时间复杂度是o(1);

图结构示例:

54a751a0-0db5-11ee-962d-dac502259ad0.png

hash函数的作⽤:避免插入的时候字符串的⽐较;hash函数计算出来的值通过对数组⻓度的取模

能随机分布在数组当中;

hash函数⼀般返回的是64位整数,将多个⼤数映射到⼀个⼩数组中,必然会产⽣冲突;

如何选取hash函数?

选取计算速度快;

哈希相似字符串能保持强随机分布性(防碰撞);

murmurhash1,murmurhash2,murmurhash3,siphash(redis6.0当中使⽤,rust等⼤多数语⾔选⽤的hash算法来实现hashmap),cityhash都具备强随机分布性;测试地址如下:https://github.com/aappleby/smhasher

负载因⼦:数组存储元素的个数/数组⻓度;负载因⼦越⼩,冲突越⼩;负载因⼦越⼤,冲突越⼤;

hash冲突解决⽅案:○ 链表法引⼊链表来处理哈希冲突;也就是将冲突元素⽤链表链接起来;这也是常⽤的处理冲突的⽅式;但是可能出现⼀种极端情况,冲突元素⽐较多,该冲突链表过⻓,这个时候可以将这个链表转换为红⿊树;由原来链表时间复杂度 o(n) 转换为红⿊树时间复杂度o(log2n) ;那么判断该链表过⻓的依据是多少?可以采⽤超过256(经验值)个节点的时候将链表结构转换为红⿊树结构;○ 开放寻址法将所有的元素都存放在哈希表的数组中,不使⽤额外的数据结构;⼀般使⽤线性探查的思路解决;

当插⼊新元素的时,使⽤哈希函数在哈希表中定位元素位置;

检查数组中该槽位索引是否存在元素。如果该槽位为空,则插⼊,否则3;

在 2 检测的槽位索引上加⼀定步⻓接着检查2;加⼀定步⻓分为以下⼏种:

i+1,i+2,i+3,i+4 ... i+n

i-1^2^ ,i+2^2^ ,i-3^2^ ,1+4^2^ ...这两种都会导致同类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 和 Hj;

同样的hashtable中节点存储了key和val,hashtable并没有要求key的⼤⼩顺序,我们同样可以修改代码让插⼊存在的数据变成修改操作;

优点:访问速度更快;不需要进行字符串比较;

缺点:需要引⼊策略避免冲突,存储效率不⾼;空间换时间;

1.5 总结

红⿊树和hashtable都不能解决海量数据问题,它们都需要存储具体字符串,如果数据量大,提供不了⼏百G的内存;所以需要尝试探寻不存储key的⽅案,并且拥有hashtable的优点(不需要⽐较字符串);

2. 布隆过滤器

定义:布隆过滤器是⼀种概率型数据结构,它的特点是⾼效的插入和查询,能明确告知某个字符串⼀定不存在或者可能存在;

布隆过滤器相⽐传统的查询结构(例如:hash,set,map等数据结构)更加高效,占⽤空间更小;但是其缺点是它返回的结果是概率性的,也就是说结果存在误差的,虽然这个误差是可控的;同时它不支持删除操作;

组成:位图(bit数组)+ n个hash函数

54b3ed70-0db5-11ee-962d-dac502259ad0.png

原理:当⼀个元素加⼊位图时,通过k个hash函数将这个元素映射到位图的k个点,并把它们置为1;当检索时,再通过k个hash函数运算检测位图的k个点是否都为1;如果有不为1的点,那么认为不存在;如果全部为1,则可能存在(存在误差);

54d1c1ba-0db5-11ee-962d-dac502259ad0.png

在位图中每个槽位只有两种状态(0或者1),⼀个槽位被设置为1状态,但不明确它被设置了多少 次;也就是不知道被多少个str1哈希映射以及是被哪个hash函数映射过来的;所以不⽀持删除操作;

在实际应⽤过程中,布隆过滤器该如何使⽤?要选择多少个hash函数,要分配多少空间的位图,存储多少元素?另外如何控制假阳率(布隆过滤器能明确⼀定不存在,不能明确⼀定存在,那么存在的判断是有误差的,假阳率就是错误判断存在的概率)?

n--布隆过滤器中元素的个数,如上图只有str1和str2两个元素那么n=2
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));

假定我们选取这四个值为:n = 4000p = 0.000000001m = 172532k = 30

四个值的关系:

54e590b4-0db5-11ee-962d-dac502259ad0.png54fd5ffa-0db5-11ee-962d-dac502259ad0.png5516ecfe-0db5-11ee-962d-dac502259ad0.png

在实际应⽤中,我们确定n和p,通过上⾯的计算算出m和k;也可以在⽹站上选取合适的值:https://hur.st/bloomfilter

已知k,如何选择k个hash函数?

//采⽤⼀个hash函数,给hash传不同的种⼦偏移值
//#defineMIX_UINT64(v)((uint32_t)((v>>32)^(v)))
uint64_thash1=MurmurHash2_x64(key,len,Seed);
uint64_thash2=MurmurHash2_x64(key,len,MIX_UINT64(hash1));
for(i=0;i< k; i++) // k 是hash函数的个数
{
  Pos[i] = (hash1 + i*hash2) % m; // m 是位图的⼤⼩
}
// 通过这种⽅式来模拟 k 个hash函数 跟我们前⾯开放寻址法 双重hash是⼀样的思路




审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Linux系统
    +关注

    关注

    4

    文章

    590

    浏览量

    27307
  • AVL
    AVL
    +关注

    关注

    0

    文章

    14

    浏览量

    10030
  • STL
    STL
    +关注

    关注

    0

    文章

    85

    浏览量

    18289
  • Hash算法
    +关注

    关注

    0

    文章

    43

    浏览量

    7379

原文标题:Linux服务器 | 数据去重hash与布隆过滤器

文章出处:【微信号:嵌入式开发AIoT,微信公众号:嵌入式开发AIoT】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    linux服务器和windows服务器

    Linux服务器表现出更好的性能和稳定性,因此广泛应用于科学计算、大数据处理和网络服务器等领域。 另方面,Windows
    发表于 02-22 15:46

    求教:linux系统和WEB服务器什么关系?WEB服务器和网页又是什么关系?

    最近在学习arm上linux系统移植以及WEB服务器,有几个问题非常非常困惑,希望大家能帮忙解答一下。1.linux操作系统和web服务器
    发表于 10-10 20:20

    如何在linux服务器上使用hanlp

    `关于如何在linux服务器上使用hanlp也有分享过篇,但分享的内容与湘笑的这篇还是不同的。此处分享一下湘笑的这篇hanlp在
    发表于 03-04 10:29

    Linux和Windows的登录和使用Linux服务器的方式

    关于登录Linux服务器的方式有很多种,本文重点介绍了Linux和Windows的登录和使用Linux
    发表于 07-05 07:54

    探讨一下关于STM32的中断系统

    大大增加,而且中断的设置也更加复杂。今天就将来探讨一下关于STM32的中断系统。1 基本概念ARM Coetex-M3内核共支持256个中断,其中16个内部中断,2
    发表于 08-17 08:29

    探讨一下关于电机轴承的数据

    这篇和大家探讨一下关于电机轴承的数据集电机轴承的数据集目前较多采用的是CWRU(凯斯西储大学轴承数据中心)这是个针对于全球学者的公开
    发表于 09-08 06:52

    请问一下怎样安装种TFTP服务器

    请问一下怎样安装种TFTP服务器呢?有哪些安装步骤呢?
    发表于 12-27 07:25

    基于Linux系统的FTP服务器的实现

    为了在Linux系统实现安全、高效的FTP服务器,选择了具有小巧轻快、安全易用等优点的服务器软件vsftpd。通过对Linux平台下FTP
    发表于 07-24 15:36 39次下载

    linuxsamba服务器搭建配置

    linuxsamba服务器搭建配置是使用linux开发系统时经常要配置的步,只有这频配置好,
    发表于 03-19 18:59 13次下载

    简单探讨一下关于电线电缆的结构材料的相关知识

    是什么?接下来,淇玥高温线缆小编和大家探讨一下关于电线电缆的结构材料的相关知识。 从电线电缆的横截面来观察分析不同种类的产品,在结构元件上,总体可以分为导线、绝缘层、屏蔽和护层以及填充元件和承拉元件,其中导线和
    发表于 09-10 10:07 855次阅读

    LinuxApache服务器的安装和配置

    LinuxApache服务器的安装和配置(现代电源技术的发展概况)-LinuxApache服务器
    发表于 08-31 16:22 8次下载
    <b class='flag-5'>Linux</b><b class='flag-5'>下</b>Apache<b class='flag-5'>服务器</b>的安装和配置

    如何在linux服务器打开端口

    有时我们可能需要在Linux服务器打开端口或在Linux服务器的防火墙启用端口来运行特定的应
    的头像 发表于 10-17 16:22 1.2w次阅读

    如何使用Checkmk监控Linux服务器

    `Checkmk` 是用于监控 Linux 服务器的最常用和用户友好的应用程序之。它可以检查与您的 Linux 服务器连接的
    的头像 发表于 02-17 10:46 1139次阅读
    如何使用Checkmk监控<b class='flag-5'>Linux</b><b class='flag-5'>服务器</b>?

    服务器数据恢复-LINUX误删除/格式化的数据恢复方案

    服务器数据恢复环境: 基于EXT2/EXT3/EXT4/Reiserfs/Xfs文件系统的Linux操作系统。 服务器故障: LINUX
    的头像 发表于 09-15 15:29 886次阅读

    服务器数据恢复—Linux网站服务器硬盘出现坏扇区的数据恢复案例

    服务器数据恢复环境: linux操作系统网站服务器,该服务器上部署了几十个网站,使用
    的头像 发表于 10-09 16:26 140次阅读