布隆过滤器:基于哈希函数的原理、应用解析

文章目录

  • 一、引言
    • 1、布隆过滤器的概念简介
    • 2、布隆过滤器是基于哈希函数的强大工具
  • 二、布隆过滤器基础知识
    • 1、布隆过滤器的工作原理
    • 2、布隆过滤器的空间效率分析
    • 3、布隆过滤器的性能特点
  • 三、布隆过滤器的应用场景
    • 1、数据库查询优化
    • 2、例子
  • 四、布隆过滤器的实现与优化
    • 1、常见的布隆过滤器库
    • 2、自定义布隆过滤器的实现步骤
    • 3、降低误报率的策略

一、引言

1、布隆过滤器的概念简介

**布隆过滤器(Bloom Filter)**是一种空间效率极高的概率型数据结构,它利用位图和哈希函数来快速判断一个元素是否属于某个集合。布隆过滤器不是传统意义上的过滤器,它不能完整地存储数据,而是以一种紧凑的方式表示数据可能存在的集合。

2、布隆过滤器是基于哈希函数的强大工具

布隆过滤器的核心机制是基于哈希函数的映射和位图将哈希与位图结合。哈希函数能够将输入数据均匀地映射到一个固定大小的范围内,而位图则提供了一种紧凑的数据表示方式。在布隆过滤器中,多个哈希函数被用于将数据映射到位图的不同位置上,并设置相应的位为1来表示数据可能存在。在查询时,只需通过同样的哈希函数计算并检查位图中对应位置的值即可判断数据是否存在。这种基于哈希函数的映射方式不仅实现了空间的高效利用,还保证了查询的快速性。


二、布隆过滤器基础知识

1、布隆过滤器的工作原理

  • 位图与哈希函数的结合

布隆过滤器主要由两部分组成:一个很长的二进制向量(即位图)和一系列随机映射函数(即哈希函数)。二进制向量中的每一位初始时都设置为0。当添加一个新元素时,该元素会经过k个哈希函数的计算,得到k个哈希值。这k个哈希值对应到位图中的k个位置,并将这些位置上的值设置为1。因此,布隆过滤器利用位图和哈希函数的结合,实现了对元素的添加操作。

下图中假设 x,y,z 通过三个不同的哈希函数映射在不同的位置上,集合元素x、y、z分别被映射到位图的某些位置,并且这些位置被标记为1。这表明这些位置在布隆过滤器中已经被设置为1,表示这些元素可能存在于集合中。

在这里插入图片描述

元素w不在集合{x, y, z}中,因为它哈希到了一个包含0的位图位置。

哈希函数的选择对布隆过滤器的性能至关重要。好的哈希函数应该具有均匀性、一致性和冲突最小化等特点,以确保布隆过滤器的误报率尽可能低。同时,哈希函数的计算速度也直接影响到布隆过滤器的查询性能。因此,在实际应用中,需要根据具体场景选择合适的哈希函数来构建高效的布隆过滤器。

  • 元素添加与查询过程

添加元素到布隆过滤器中的过程相对简单。首先,将要添加的元素通过k个哈希函数进行计算,得到k个哈希值。然后,根据这些哈希值在位图中找到对应的k个位置,并将这些位置上的值设置为1。如果某些位置上的值已经是1,则不需要进行任何操作。

由于哈希函数的特性,布隆过滤器在处理数据时具有一定的概率性。这意味着它可能会存在误报(false positive)的情况,即判断某个元素属于集合但实际上并不属于。然而,通过合理选择哈希函数和调整位图的大小,可以降低误报率,使得布隆过滤器在实际应用中仍然具有非常高的实用价值。

在这里插入图片描述

{ A,B,C }通过哈希函数映射在不同的位置。此时我们查找元素 X,通过哈希函数得到的三个下标上的元素均为1,但是元素 X 不存在于集合中。

查询一个元素是否存在于布隆过滤器中的过程也相对直接。同样地,将要查询的元素通过k个哈希函数进行计算,得到k个哈希值。然后,检查这些哈希值对应到位图上的位置,如果所有位置上的值都是1,则认为该元素可能存在于集合中。然而,需要注意的是,由于哈希冲突的存在,即使所有位置上的值都是1,也不能确定该元素一定存在于集合中,因此布隆过滤器的查询结果具有概率性。

  • 误报率(False Positive Rate)的解释

误报率表示的是当一个元素查询结果为存在时,但实际上该元素并不存在的概率。由于布隆过滤器是通过哈希函数将元素映射到位图上的,因此存在哈希冲突的可能性。当两个不同的元素经过哈希函数计算后得到相同的哈希值时,就会发生哈希冲突。在这种情况下,如果一个元素被错误地标记为存在(即其对应的位图位置上的值为1),就会导致误报。误报率与布隆过滤器的位图大小、哈希函数的个数以及集合中元素的个数有关。通常情况下,通过增加位图的大小和哈希函数的个数,可以降低误报率,但也会增加空间和时间开销。

⚠️总结来说,布隆过滤器通过位图和哈希函数的结合,实现了高效的元素添加和查询操作。然而,由于其基于哈希函数的特性,布隆过滤器的查询结果具有概率性,存在误报的可能性。因此,在使用布隆过滤器,要注意:布隆过滤器如果说某个元素不存在时,该元素一定不存在,如果该元素存在时,该元素可能存在,因为有些哈希函数存在一定的误判。

  • 删除布隆过滤器中的元素

布隆过滤器的一个主要限制是它不支持删除操作。这是因为布隆过滤器是基于位图和哈希函数实现的,当一个元素被添加到过滤器中时,它会被哈希到多个位上并将这些位设置为1。然而,当尝试删除一个元素时,我们无法简单地将其对应的位重置为0,因为这可能会影响到其他已经添加的元素。

具体来说,如果我们将某个元素对应的位重置为0,那么可能会破坏掉其他已经添加到过滤器中的元素的哈希表示。因为多个元素可能哈希到同一个位上,而这个位被某个元素“占用”时,我们不能确定它是否只被这一个元素所使用。

因此,一旦一个元素被添加到布隆过滤器中,它就不能被直接删除。这是布隆过滤器的一个固有特性,也是它与其他数据结构(如哈希表或集合)相比的一个主要区别。

⭕️ 但是我们可以通过将布隆过滤器中的每个比特位扩展成一个小的计数器(通常称为计数布隆过滤器或Counting Bloom Filter),可以实现对元素的删除操作。这种方法通过牺牲更多的存储空间来换取删除功能。

在计数布隆过滤器中,每个位不再是一个简单的0或1,而是一个可以递增和递减的计数器。当插入一个元素时,通过k个哈希函数计算出的k个哈希地址,将对应的k个计数器加一。当需要删除一个元素时,同样通过这k个哈希函数找到对应的计数器,并将它们减一。

通过这种方法,可以准确地跟踪每个位置上的元素计数,从而支持删除操作。然而,需要注意的是,计数布隆过滤器仍然无法完全避免误报(False Positive)的情况。即使某个元素的计数器被正确减至零,由于哈希冲突的存在,其他元素可能仍然会导致该位置上的计数器非零,从而产生误报。

此外,计数布隆过滤器还需要考虑计数器溢出的问题。如果计数器的值超过了其能够表示的范围,就会导致数据丢失和误操作。因此,在选择计数器的位数时需要根据实际应用场景进行权衡。

2、布隆过滤器的空间效率分析

布隆过滤器的空间效率分析主要体现在其相对于其他数据结构的空间占用优势上。布隆过滤器通过使用位图和哈希函数,实现了对元素存在性的高效判断,同时显著降低了空间占用。

  • 与其他数据结构的空间对比

与常见的数据结构如listsetmap等相比,布隆过滤器在空间效率上具有显著优势。这些传统数据结构通常需要存储元素的完整信息,而布隆过滤器只存储位图中的位信息,且每一位只占用极少的空间(通常是1比特)。因此,在存储相同数量的元素时,布隆过滤器所需的存储空间远小于其他数据结构。

  • 影响空间效率的关键因素
  1. 位图的大小:位图是布隆过滤器存储元素信息的主要数据结构。位图的大小直接决定了布隆过滤器能够存储的元素数量以及误报率的高低。通常情况下,位图越大,能够存储的元素数量越多,同时误报率也会相应降低。
  2. 哈希函数的个数和性质:哈希函数在布隆过滤器中起到了将元素映射到位图的关键作用。哈希函数的个数和性质直接影响到布隆过滤器的空间效率和误报率。一般来说,使用更多的哈希函数可以降低误报率,但同时也会增加计算开销和空间占用。此外,哈希函数的均匀性和分散性也对布隆过滤器的性能有重要影响。
  3. 元素的数量:存储的元素数量越多,布隆过滤器所需的位图空间就越大。这是因为每个元素都需要通过哈希函数映射到位图中的多个位置,并设置相应的位为1。
  4. 误报率的设定:误报率是布隆过滤器的一个重要指标,它表示了当查询一个不存在的元素时错误地返回存在的概率。误报率的设定会直接影响到布隆过滤器的空间占用。通常情况下,误报率越低,所需的位图空间就越大。

3、布隆过滤器的性能特点

插入和查询的时间复杂度都是O(k),这意味着无论集合中元素的数量如何增加,插入和查询的时间都将保持稳定,不会随着元素数量的增长而显著增长。这是因为布隆过滤器使用位图和哈希函数来表示集合,查询和插入操作只涉及到位图的访问和更新,而无需遍历整个集合。

其次,哈希函数的选择对布隆过滤器的性能具有重要影响。一个好的哈希函数能够近似等概率地将字符串映射到各个位上,从而减少哈希冲突的可能性,提高布隆过滤器的准确性和性能。哈希函数的个数k也是影响性能的关键因素,k值的选择需要根据实际情况进行权衡。过多的哈希函数会增加计算复杂度,而过少的哈希函数则可能导致较高的误报率。

总的来说,布隆过滤器以其高效的插入和查询操作以及灵活的哈希函数选择,成为了处理大规模数据集合的理想选择。然而,需要注意的是,布隆过滤器存在误报的可能性,即可能会错误地判断一个不存在的元素为存在。因此,在使用布隆过滤器时,需要根据具体的应用场景和需求来选择合适的参数配置,以达到最优的性能和准确性。


三、布隆过滤器的应用场景

1、数据库查询优化

  • 过滤不存在的记录,减少磁盘I/O

布隆过滤器可以有效地过滤不存在的记录,从而避免不必要的磁盘I/O操作。那么,当一个新的查询请求到达时,首先通过布隆过滤器检查该记录是否可能存在于数据库中。如果布隆过滤器返回结果为“不存在”,则可以直接拒绝该查询请求,无需进一步访问数据库。这样可以显著减少磁盘I/O操作,提高查询效率。

在实际应用中,布隆过滤器可以与数据库查询语句结合使用。例如,在执行查询操作之前,可以先将查询条件通过布隆过滤器进行过滤,只保留可能存在于数据库中的记录,然后再执行实际的查询操作。这样可以确保查询操作只针对可能存在的记录进行,避免了对大量不存在记录的无效查询。

2、例子

假设给了两个文件,分别有100亿个query,我们只有1G内存,如何找到两个文件交集?分别给出精确算法和近似算法?

假设一个 query 平均是50byte,1G约等于10亿字节。那么100亿个query是500G。

精确算法

由于内存限制,我们不能一次性加载所有query到内存中。因此,需要采用分块处理的策略。

  1. 哈希分块
    • 使用哈希函数将两个文件分别分成多个小块,每个块的大小适中,使得可以加载到内存中。
    • 对每个块进行排序,以便后续快速查找交集。
  2. 逐块对比
    • 逐块比较两个文件中的query。对于每一对块,将其中一个块加载到内存中,另一个块则使用外部排序的方法(如多路归并排序)进行遍历。
    • 在内存中执行二分查找或使用哈希表来查找交集。
  3. 合并结果
    • 将所有找到的交集合并到一个输出文件中。
  4. 去重:
    • 由于可能存在重复的交集,在写入输出文件之前,需要对结果进行去重处理。可以使用 map、set等容器。

这个算法虽然精确,但可能非常耗时,因为它涉及到多次磁盘I/O操作和排序操作。该文中也有涉猎 -> 深入探索位图技术:原理及应用

近似算法

为了在处理大数据集时提高效率,可以采用近似算法来找到交集的近似解。

  1. 布隆过滤器

    • 使用布隆过滤器来存储一个文件中的所有query。布隆过滤器允许快速检查一个元素是否可能存在于集合中,但可能会产生误报(即,将不存在的元素错误地识别为存在)。
    • 加载第一个文件的query到布隆过滤器中。由于布隆过滤器的内存占用相对较小,因此可以在有限的内存中存储大量的query。
  2. 检查交集

    • 遍历第二个文件的query,使用布隆过滤器检查每个query是否可能存在于第一个文件中。
    • 将布隆过滤器识别为可能存在的query作为交集的近似结果输出。

请注意,由于布隆过滤器的误报性质,这种算法只能给出交集的近似解,而不是精确解。误报率取决于布隆过滤器的大小和哈希函数的数量。通过调整这些参数,可以在一定程度上控制误报率,但无法完全消除它。


四、布隆过滤器的实现与优化

1、常见的布隆过滤器库

  • 开源库
    • Google Guava:Java语言的开源库,提供了布隆过滤器的实现。
    • RedisBloom:针对Redis的布隆过滤器模块,提供丰富的布隆过滤器功能。
    • pybloom:Python语言的布隆过滤器库。
    • bloomfilter-cpp:C++语言的布隆过滤器库

2、自定义布隆过滤器的实现步骤

struct HashFunc1 {
	//BKDR
	size_t operator()(const string& s){
		size_t hash = 0;
		for (auto ch : s)
		{
			hash *= 131;
			hash += ch;
		}

		return hash;
	}
};
struct HashFunc2 {
	// AP
	size_t operator()(const 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 HashFunc3 {
	// DJB
	size_t operator()(const string& s){
		size_t hash = 5381;
		for (auto ch : s)
			hash = hash * 33 ^ ch;
		return hash;
	}
};
template<size_t N, class K = string,
	class Hash1 = HashFunc1,
	class Hash2 = HashFunc2,
	class Hash3 = HashFunc3>
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;

        _bs->set(hash1);
        _bs->set(hash2);
        _bs->set(hash3);


    }

    bool Test(const K& key) {
        size_t hash1 = Hash1()(key) % M;
        if (_bs->test(hash1) == false)
            return false;

        size_t hash2 = Hash2()(key) % M;
        if (_bs->test(hash2) == false)
            return false;

        size_t hash3 = Hash3()(key) % M;
        if (_bs->test(hash3) == false)
            return false;

        // 存在误判(有可能3个位都是跟别人冲突的,所以误判)
        return true;
    }
private:
    static const size_t M = 5 * N;
    std::bitset<M>* _bs = new std::bitset<M>;
};
  1. Set方法:用于将元素添加到布隆过滤器中。它计算元素的三个哈希值,并将对应位置上的位设置为1。
  2. Test方法:用于检查元素是否可能存在于布隆过滤器中。它同样计算元素的三个哈希值,并检查对应位置上的位是否都为1。如果有任何一位为0,则确定元素一定不存在;如果所有位都为1,则返回true,但存在误报的可能。

3、降低误报率的策略

  • 增加位图长度

布隆过滤器的误报率与其使用的位图(bit array)大小直接相关。位图越长,能提供的唯一标识就越多,从而减少了哈希冲突的可能性。因此,增加位图长度可以有效降低误报率。但需要注意的是,位图长度的增加也会导致空间需求的增加,所以需要在误报率和空间使用之间找到平衡。

  • 使用多个独立的哈希函数

布隆过滤器通常使用多个哈希函数将元素映射到位图的不同位置。使用更多的哈希函数可以增加元素在位图中的覆盖面积,进一步减少哈希冲突的可能性。然而,这也增加了计算复杂性和哈希函数的选择难度。因此,在选择哈希函数数量时,需要权衡误报率和计算效率。

  • 动态调整布隆过滤器大小

在某些情况下,可以根据实际需求动态调整布隆过滤器的大小。例如,当检测到误报率较高时,可以扩大位图长度或增加哈希函数数量来降低误报率。同样地,当空间资源紧张时,也可以适当缩小位图长度或减少哈希函数数量以节省空间。这种动态调整策略需要根据实际应用场景进行灵活配置。

需要注意的是,虽然这些策略可以降低误报率,但它们并不能完全消除误报。布隆过滤器是一种概率数据结构,其设计本身就允许存在一定的误报率。因此,在使用布隆过滤器时,需要充分考虑其特性并根据实际需求进行权衡和配置。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/508837.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

libusb Qt使用记录

1.libusb 下载 &#xff0c;选择编译好的二进制文件&#xff0c;libusb-1.0.26-binaries.7z libusb Activity 2. 解压 3. 在 Qt Widgets Application 或者 Qt Console Application 工程中导入库&#xff0c;Qt 使用的是 minggw 64编译器&#xff0c;所以选择libusb-MinGW-x64。…

用户故事与用例:软件开发的双翼

用户故事与用例&#xff1a;软件开发的双翼 引言 在敏捷软件开发中&#xff0c;理解用户需求是成功交付高质量产品的关键。本文将详细介绍两种收集和定义需求的流行技术&#xff1a;用户故事和用例。我们将探讨它们的理论基础、区别、联系&#xff0c;以及如何在实际工作中应…

提升LLM效果的几种简单方法

其实这个文章想写很久了&#xff0c;最近一直在做大模型相关的产品&#xff0c;经过和团队成员一段时间的摸索&#xff0c;对大模型知识库做一下相关的认知和总结。希望最终形成一个系列。 对于知识库问答&#xff0c;现在有两种方案&#xff0c;一种基于llamaindex&#xff0…

2024年04月在线IDE流行度最新排名

点击查看最新在线IDE流行度最新排名&#xff08;每月更新&#xff09; 2024年04月在线IDE流行度最新排名 TOP 在线IDE排名是通过分析在线ide名称在谷歌上被搜索的频率而创建的 在线IDE被搜索的次数越多&#xff0c;人们就会认为它越受欢迎。原始数据来自谷歌Trends 如果您相…

WebSocket用户验证

在WebSocket中&#xff0c;如何携带用户的验证信息 一、在OnMessage中进行验证 客户端在连接到服务器后&#xff0c;客户端通过发送消息&#xff0c;服务器端在OnMessage方法中&#xff0c;进行信息验证&#xff0c;这种方式需要将用户身份验证及接收用户消息进行混合处理&am…

分布式全闪占比剧增 152%,2023 年企业存储市场报告发布

近日&#xff0c;IDC 发布了 2023 年度的中国存储市场报告。根据该报告&#xff0c;在 2023 年软件定义存储的市场占比进一步扩大&#xff0c;分布式全闪的增长尤其亮眼&#xff0c;其市场份额从 2022 年的 7% 剧增到 2023 年的 17.7%&#xff0c;增长了 152%。 01 中国企业存…

备战蓝桥杯---贪心刷题2

话不多说&#xff0c;直接看题&#xff1a; 首先我们大致分析一下&#xff0c;先排序一下&#xff0c;Kn&#xff0c;那就全部选。 当k<n时&#xff0c;k是偶数&#xff0c;那么结果一定非负&#xff0c;因为假如负数的个数有偶数个&#xff0c;那么我们成对选它&#xff0…

【问题处理】银河麒麟操作系统实例分享,鲲鹏服务器GaussDB测试ping延迟过高问题

1.问题环境 系统环境 物理机 网络环境 私有网络 硬件环境 机型 TaiShan 200 (Model 2280) (VD) 处理器 HUAWEI Kunpeng 920 5250 内存 32GB*16 显卡 无 主板型号 BC82AMDDRE 架构 ARM 固件版本 iBMC固件版本 3.03.00.31 (U82) 单板ID 0x00a9 BIOS版本 1.8…

SpringBoot mybatis-starter解析

mybatis-starter使用指南 自动检测工程中的DataSource创建并注册SqlSessionFactory实例创建并注册SqlSessionTemplate实例自动扫描mappers mybatis-starter原理解析 注解类引入原理 查看对应的autoconfigure包 MybatisLanguageDriverAutoConfiguration 主要是协助使用注解来…

数论与线性代数——整除分块【数论分块】的【运用】【思考】【讲解】【证明(作者自己证的QWQ)】

文章目录 整除分块的思考与运用整除分块的时间复杂度证明 & 分块数量整除分块的公式 & 公式证明公式证明 代码code↓ 整除分块的思考与运用 整除分块是为了解决一个整数求和问题 题目的问题为&#xff1a; ∑ i 1 n ⌊ n i ⌋ \sum_{i1}^{n} \left \lfloor \frac{n}{…

用ChatGPT出题,完全做不完

最近小朋友正在学习加减法&#xff0c;正好利用ChatGPT来生成加减法练习题&#xff0c;小朋友表示够了&#xff0c;够了&#xff0c;完全做不完。本文将给大家介绍如何利用ChatGPT来生成练习题。 尚未获得ChatGPT的用户&#xff0c;请移步&#xff1a;五分钟开通GPT4.0。 角色…

Qt 实现简易的视频播放器,功能选择视频,播放,暂停,前进,后退,进度条拖拉,视频时长显示

1.效果图 2.代码实现 2.1 .pro文件 QT core gui multimedia multimediawidgets 2.2 .h文件 #ifndef VIDEOPLAYING_H #define VIDEOPLAYING_H#include <QWidget> #include<QFileDialog>#include<QMediaPlayer> #include<QMediaRecorder> #in…

【C语言进阶】- 内存函数

内存函数 1.1 内存函数的使用1.2 memcpy函数的使用1.3 memcpy函数的模拟实现2.1 memmove函数的使用2.2 memmove函数的模拟实现2.3 memcmp函数的使用2.4 memset函数的使用 1.1 内存函数的使用 内存函数就是对内存中的数据进行操作的函数 1.2 memcpy函数的使用 void* memcpy ( …

Tomcat调优总结(Tomcat自身优化、Linux内核优化、JVM优化)

Tomcat自身的调优是针对conf/server.xml中的几个参数的调优设置。首先是对这几个参数的含义要有深刻而清楚的理解。以tomcat8.5为例&#xff0c;讲解参数。 同时也得认识到一点&#xff0c;tomcat调优也受制于linux内核。linux内核对tcp连接也有几个参数可以调优。 因此我们可…

每天五分钟深度学习:神经网络和深度学习有什么样的关系?

本文重点 神经网络是一种模拟人脑神经元连接方式的计算模型&#xff0c;通过大量神经元之间的连接和权重调整&#xff0c;实现对输入数据的处理和分析。而深度学习则是神经网络的一种特殊形式&#xff0c;它通过构建深层次的神经网络结构&#xff0c;实现对复杂数据的深度学习…

用Python实现办公自动化(自动化处理PDF文件)

自动化处理 PDF 文件 目录 自动化处理 PDF 文件 谷歌浏览器 Chrome与浏览器驱动ChromeDriver安装 &#xff08;一&#xff09;批量下载 PDF 文件 1.使用Selenium模块爬取多页内容 2.使用Selenium模块下载PDF文件 3.使用urllib模块来进行网页的下载和保存 4.使用urllib…

AI预测福彩3D第23弹【2024年4月1日预测--第5套算法开始计算第5次测试】

今天&#xff0c;咱们继续进行本套算法的测试&#xff0c;本套算法目前也已命中多次。今天为第五次测试&#xff0c;仍旧是采用冷温热趋势结合AI模型进行预测。好了&#xff0c;废话不多说了。直接上结果~ 仍旧是分为两个方案&#xff0c;1大1小。 经过人工神经网络计算并进行权…

基于FPGA的图像累积直方图verilog实现,包含tb测试文件和MATLAB辅助验证

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 Vivado2019.2 matlab2022a 3.部分核心程序 timescale 1ns / 1ps // // Company: // Engineer: // // Design Name: // …

MarkDown之时序图并行、条件、循环、可选高级语法(三十)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

Jenkins首次安装选择推荐插件时出现”No such plugin cloudbees-folder”解决方案

安装Jenkins成功之后&#xff0c;首次启动Jenkins后台管理&#xff0c;进入到安装插件的步骤&#xff0c;选择"推荐安装"&#xff0c;继续下一步的时候出现错误提示&#xff1a; 出现一个错误 安装过程中出现一个错误&#xff1a;No such plugin&#xff1a;cloudb…