哈希 -- 位图、布隆过滤器、海量数据处理

news2025/1/12 17:27:52

目录

  • 一、位图
    • 1.1 经典题目
    • 1.2 位图概念
    • 1.3 位图的应用
    • 1.4 关于位图的三个经典问题
  • 二、布隆过滤器
    • 2.1 布隆过滤器的提出
    • 2.2 布隆过滤器的概念
    • 2.3 布隆过滤器的插入
    • 2.4 布隆过滤器的查找
    • 2.5 布隆过滤器删除
    • 2.6 代码实现
    • 2.7 布隆过滤器的优点
    • 2.8 布隆过滤器的缺陷
    • 2.9 布隆过滤器的应用场景
  • 三、海量数据处理
    • 3.1 布隆过滤器
    • 3.2 位图应用
    • 3.3 哈希切割

一、位图

1.1 经典题目

假设有这么一道题目:
给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中。
1、先把数据用set存起来,再查找一个无符号整数可以吗?
不可以!为什么?因为40亿个整数大概要占16G内存,但是一般配置的计算机都是开不出16G的内存的,除非有些超级计算机,所以这个方法并不适用于所有计算机。
2、排序+二分查找可以吗?
也不适合,因为数据量太大而不能一次性全部加载到内存中,所以需要在磁盘中进行归并排序,要进行大量的IO,效率低;并且二分查找的时候也是要在磁盘中进行的,所以这个方法也不适合解决这个问题!
这也不行,那也不行,那该如何解决这个问题呢?
上面两种方法之所以不适用,是因为数据量太大了,并且又是整形,所占的内存空间太多,所以我们不能开辟那么大的内存出来,那如果我们能够用一个很小的空间标志出这些数据是否存在,那不就可以了吗?在这道题中我们的目标是知道一个数在不在这堆数里面,是在不在的问题,所以我们完全没有必要把这40亿个整数存起来,只需要标志一下这些数是否存在就可以了,标志一个数在不在我们其实只需要一个比特位就可以了,某个数在就把对应的比特位设置成1,不在就把对应的比特位设置成0,这样一来,本来需要4个字节,即32个比特位的空间存放一个整形,现在变成了只需要一个比特位标志,所以40亿个整数占用的空间就从16G变成了500M,500M的内存我们是可以开辟出来的,我们把开辟出来标志数据在不在的这段空间叫做位图,这样我们就能把这40亿个整数都标志到这个位图的对应位置,再查找某一个数在不在的时候就只需要查看位图中对应位置的是否为1,是1就表示这个数在,是0就表示这个数不在。
如此一来,就能把这道题给解决了。

1.2 位图概念

所谓位图,就是用每一位来存放某种状态,适用于海量数据,数据无重复的场景。通常是用来判断某个数据存不存在的。
因为500M内存我们的计算机是能够开辟出来的,所以我们用的是直接定址法,即每一个整数直接映射到位图上的对应的位置。
在这里插入图片描述
位图代码实现:

namespace BitSetC
{
	//N是非类型模板参数
	template <size_t N>
	class bitset
	{
	public:
		//构造函数,N表示该位图能映射的数据的最大值,每一个映射的值是一个比特位,所以应该根据
		//N的值求出我们需要开辟多少个char的空间,因为/的特点是把余数舍去了,所以为了映射数据
		//时不越界,所以应该多开辟一个char的空间,所以是开辟N/8+1个空间
		bitset()
		{
			_bs.resize(N / 8 + 1);
		}
		void set(size_t x)
		{
			//计算x应该映射到第几个char中
			size_t i = x / 8;
			//计算x在第i个char中的第几个位置
			size_t j = x % 8;
			//通过位运算把第i个char的第j个位置设置为1
			//就把这个x设置进位图了
			_bs[i] |= (1 << j);
		}
		bool test(size_t x)
		{
			//计算x应该映射到第几个char中
			size_t i = x / 8;
			//计算x在第i个char中的第几个位置
			size_t j = x % 8;

			//利用位运算检查第i个char的第j个位置是否被设置成1了
			//如果设置了,就证明这个x在位图中,否则,x不在位图中
			if (((_bs[i] >> j) & 1) == 1)
			{
				return true;
			}
			else
			{
				return false;
			}
		}
		void reset(size_t x)
		{
			//计算x应该映射到第几个char中
			size_t i = x / 8;
			//计算x在第i个char中的第几个位置
			size_t j = x % 8;
			//通过位运算把第i个char中的第j位设置为0即可
			_bs[i] &= (~(1 << j));
		}
	private:
		//这里的vector的元素可以是char,也可以是其他类型
		vector<char> _bs;
	};
}

1.3 位图的应用

  1. 快速查找某个数据是否在一个集合中
  2. 排序 + 去重
  3. 求两个集合的交集、并集等
  4. 操作系统中磁盘块标记

1.4 关于位图的三个经典问题

1、 给定100亿个整数,设计算法找到只出现一次的整数?
虽然是100亿个整数,但是整数最多也就40多亿个,所以一个位图占用的空间还是500M,因为要找出只出现一次的整数,如果只用一个位图只能标志一个数在不在,并不能很好的统计该数出现的次数,所以我们可以用两个位图来表示一个数字出现的次数,因为两个比特位可以表示出四种情况,00表示出现了0次,01表示出现了1次,10表示出现了2次,11表示出现了3次,如果一个数字出现了2次以上的就标志为11就行了,因为我们要找的是出现一次的数字,2次及以上的都是不符合要求的。

所以解决这个问题的大概思路是创建两个位图bs1和bs2,然后遍历这100亿个整数,判断bs1和bs2对应位置的情况,如果在这个数对应位置中,bs1=0,bs2=0,说明这个数还没有出现过,此时bs2设置为1;如果bs1=0,bs2=1,说明这个数字已经出现过一次,此时把bs1设置为1,bs2设置为0;如果bs1=1,bs2=0,说明这个数字已经出现了2次,这时把bs2设置为1,或者说设不设置都可以,因为这个数一定是不符合要求的。这样就能把所有数字出现的次数存放在了这两个位图中,再遍历一遍这批数,同时通过位图查看哪一些数映射到位图上对应位置的结果是bs1=0,bs2=1的数就是出现一次的数。

2、位图应用变形:1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数。
同理,找出不超过2次的整数也是先按照第1题那样把这100亿个整形设置到两个位图bs1和bs2中,然后再遍历这100亿个数,找到在位图中对应位置的bs1=0,bs2=1或者bs1=1,bs2=0的数,就是出现次数不超过2的数,统计即可。

下面是用我们自己实现的位图解决1、2问题的参考代码:

namespace BitSetC
{
	//N是非类型模板参数
	template <size_t N>
	class bitset
	{
	public:
		//构造函数,N表示该位图能映射的数据的最大值,每一个映射的值是一个比特位,所以应该根据
		//N的值求出我们需要开辟多少个char的空间,因为/的特点是把余数舍去了,所以为了映射数据
		//时不越界,所以应该多开辟一个char的空间,所以是开辟N/8+1个空间
		bitset()
		{
			_bs.resize(N / 8 + 1);
		}
		void set(size_t x)
		{
			//计算x应该映射到第几个char中
			size_t i = x / 8;
			//计算x在第i个char中的第几个位置
			size_t j = x % 8;
			//通过位运算把第i个char的第j个位置设置为1
			//就把这个x设置进位图了
			_bs[i] |= (1 << j);
		}
		bool test(size_t x)
		{
			//计算x应该映射到第几个char中
			size_t i = x / 8;
			//计算x在第i个char中的第几个位置
			size_t j = x % 8;

			//利用位运算检查第i个char的第j个位置是否被设置成1了
			//如果设置了,就证明这个x在位图中,否则,x不在位图中
			if (((_bs[i] >> j) & 1) == 1)
			{
				return true;
			}
			else
			{
				return false;
			}
		}
		void reset(size_t x)
		{
			//计算x应该映射到第几个char中
			size_t i = x / 8;
			//计算x在第i个char中的第几个位置
			size_t j = x % 8;
			//通过位运算把第i个char中的第j位设置为0即可
			_bs[i] &= (~(1 << j));
		}
	private:
		//这里的vector的元素可以是char,也可以是其他类型
		vector<char> _bs;
	};
}

//给定100亿个整数,设计算法找到只出现一次的整数?
//1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数
template <size_t N>
class TwoBitSet
{
public:
	void set(size_t x)
	{
		//x出现0次,则原来的位图组合是00,则把_bs1的x位置和_bs2的x位置设置为01
		if (!_bs1.test(x) && !_bs2.test(x))
		{
			_bs2.set(x);
		}
		//x出现1次,则原来的位图组合是01,则把_bs1的x位置和_bs2的x位置设置为10
		else if (!_bs1.test(x) && _bs2.test(x))
		{
			_bs1.set(x);
			_bs2.reset(x);
		}
		//x出现2次及以上,则原来的位图组合是10,则把_bs1的x位置和_bs2的x位置设置为11
		else if (_bs1.test(x) && !_bs2.test(x))
		{
			_bs2.set(x);
		}
	}

	//查找只出现一次的数
	bool is_once(size_t x)
	{
		if (!_bs1.test(x) && _bs2.test(x))
		{
			return true;
		}
		return false;
	}

	//1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数
	bool FindLowerTwo(size_t x)
	{
		//出现1次
		if (!_bs1.test(x) && _bs2.test(x))
		{
			return true;
		}
		//出现2次
		else if (_bs1.test(x) && !_bs2.test(x))
		{
			return true;
		}
		//出现0次或者2次以上
		return false;
	}
private:
	BitSetC::bitset<N> _bs1;
	BitSetC::bitset<N> _bs2;
};

3、给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集?
这里也肯定是用位图来解决的,因为有100亿个整数,整形的范围是固定的42亿9千万个,所以一个位图还是500M的空间。
所以先创建两个位图bs1和bs2,然后分别把这两个文件的整数设置到bs1和bs2位图中。此时我们如何找到这两个位图中的交集呢?我们知道1&1=1,1&0=0,0&1=1,而位图中的每一个位置要么是0,要么是1,如果两个文件都有同一个数,即交集,那么它们在各自位图中的映射的位置一定是一样的,所以把两个位图进行按位与操作,得到的结果就是它们的交集了,并且通过位图来查找交集还自带了去重的操作,因为交集是一个无重复元素的集合。那这两个位图怎么做按位与操作呢?其实这里不用真的把两个位图做按位与操作的,只需要在遍历这些数的时候判断该数是否同时在bs1和bs2中就可以了。

int main()
{
	//给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集?
	//假设nums1和nums2就是100亿个整数的文件
	int nums1[] = { 1,2,3,6,8,2,3,6 ,6 };
	int nums2[] = { 1,7,9,6 };

	BitSetC::bitset<10> bs1;
	BitSetC::bitset<10> bs2;
	for (const auto& e : nums1)
	{
		bs1.set(e);
	}
	for (const auto& e : nums2)
	{
		bs2.set(e);
	}
	for (size_t i = 0; i < 10; i++)
	{
	  //同一个元素两个位图都设置了说明这个元素是交集
		if (bs1.test(i) && bs2.test(i))
		{
			cout << i << " ";
		}
	}
	cout << endl;

	return 0;
}

二、布隆过滤器

2.1 布隆过滤器的提出

我们在刷抖音时,它会给我们不停地推荐新的内容,它每次推荐时要去重,去掉那些已经看过的内容。那么问题来了,抖音客户端推荐系统如何实现推送去重的? 用服务器记录了用户看过的所有历史记录,当推荐系统推荐视频时会从每个用户的历史记录里进行筛选,过滤掉那些已经存在的记录。 如何快速查找呢?

  1. 用哈希表存储用户记录。缺点:浪费空间
  2. 用位图存储用户记录。缺点:位图一般只能处理整形,如果内容编号是字符串,就无法处理了。
  3. 将哈希与位图结合,就叫做布隆过滤器。

2.2 布隆过滤器的概念

布隆过滤器是由布隆(Burton Howard Bloom)在1970年提出的 一种紧凑型的、比较巧妙的概率型数据结构,特点是高效地插入和查询,可以用来告诉你 “某样东西一定不存在或者可能存在”,它是用多个哈希函数,将一个数据映射到位图结构中的多个位置。此种方式不仅可以提升查询效率,也可以节省大量的内存空间。

2.3 布隆过滤器的插入

在这里插入图片描述
在这里插入图片描述

2.4 布隆过滤器的查找

布隆过滤器的思想是将一个元素用多个哈希函数映射到一个位图中的多个位置上,因此被映射到的位置的比特位一定为1。所以可以按照以下方式进行查找:分别计算每个哈希值对应的比特位置存储的是否为零,只要有一个为零,代表该元素一定不在哈希表中,否则可能在哈希表中。
注意:布隆过滤器如果说某个元素不存在时,该元素一定不存在,如果该元素存在时,该元素可能存在,因为有些哈希函数存在一定的误判。
比如:在布隆过滤器中查找"zhaoyun"时,假设3个哈希函数计算的哈希值为:2、4、6,刚好和其他元素的比特位重叠,即其他元素的刚好把2,4,6比特位都设置了,此时布隆过滤器告诉你该元素存在,但是该元素是不存在的。

2.5 布隆过滤器删除

布隆过滤器不能直接支持删除工作,因为在删除一个元素时,可能会影响其他元素。比如你要删除的元素的映射位置是1,3,5,那么你想删除这个元素就要把1,3,5位置都设置为0,但是可能其他元素通过哈希函数计算出来的映射位置也是1或者3或者5,所以如果把1,3,5的位置改成0的话,其它本来存在的元素也会变成不存在,这显然是不对的。基于这样的原因,有人提出既然直接置成0有可能会影响到其它元素,那么就用一个引用计数记录这个位置被映射了多少次,每一次删除的时候就减减这个引用计数,直到引用计数减为0的时候才把这个位置设置为0,这样删除就可以不影响其它元素了。
这个方法听起来确实可行,但是它真的可行吗?
其实不是的,因为某个元素存在是会有误判的,所以你怎么确定你这个元素是存在布隆过滤器里的呢?你都无法确定你这个元素是否存在,你怎么敢删除呢?就好比“zhaoyun”这个元素,假设它通过哈希函数算出来的映射位置是2,4,6,而2,4,6三个位置刚好又被其他元素都映射了,也就是说这个“zhaoyun”的存在是误判的,它压根就不存在,此时你删除“zhaoyun”,即把2,4,6三个位置的引用计数都减1,这符合逻辑吗?这显然不符合,你压根就不存在布隆过滤器中,你如何删除。所以用引用计数的方法实现布隆过滤器的删除也是不可行的,也是会影响到其他元素的,所以无论如何布隆过滤器都是不支持删除操作的。

2.6 代码实现

//针对字符串的哈希函数
struct BKDRHash
{
    size_t operator()(const string& str)
    {
        size_t hash = 0;
        for (auto ch : str)
        {
            hash = hash * 131 + ch;
        }

        return hash;
    }
};

struct APHash
{
    size_t operator()(const string& str)
    {
        size_t hash = 0;
        for (size_t i = 0; i < str.size(); i++)
        {
            size_t ch = str[i];
            if ((i & 1) == 0)
            {
                hash ^= ((hash << 7) ^ ch ^ (hash >> 3));
            }
            else
            {
                hash ^= (~((hash << 11) ^ ch ^ (hash >> 5)));
            }
        }

        return hash;
    }
};

struct DJBHash
{
    size_t operator()(const string& str)
    {
        size_t hash = 5381;
        for (auto ch : str)
        {
            hash += (hash << 5) + ch;
        }

        return hash;
    }
};

template <size_t N,class K = string,class Func1= BKDRHash, class Func2 = APHash, class Func3 = DJBHash>
class BloomFilter
{
public:
    //为了减少误判率,所以一个字符串可以通过多个哈希函数
    //映射到多个位置,只有当全部的映射位置都被设置为1了才算
    // 是这个字符串存在,只要有任意一个位置没有被映射,就说
    //明这个字符串是不存在的
    void set(const K& key)
    {
        //创建仿函数的匿名对象直接调用哈希函数计算映射位置
        //因为我们只有N个映射位置,所以需要%N才能映射到合
        // 法的对应的映射位置上
        size_t hash1 = Func1()(key) % N;
        size_t hash2 = Func2()(key) % N;
        size_t hash3 = Func3()(key) % N;

        //把通过哈希函数计算出来的这三个映射位置都设置为1,
        //代表这个字符串是存在的
        _bs.set(hash1);
        _bs.set(hash2);
        _bs.set(hash3);
    }
    bool test(const K& key)
    {
        //分别检查key通过不同哈希函数计算出来的映射位置
        //是否都被设置成了1,只要其中任意一个位置不被设
        //置,就说明这个字符串是不存在的

        size_t hash1 = Func1()(key) % N;
        if (!_bs.test(hash1))
        {
            return false;
        }

        size_t hash2 = Func2()(key) % N;
        if (!_bs.test(hash2))
        {
            return false;
        }

        size_t hash3 = Func3()(key) % N;
        if (!_bs.test(hash3))
        {
            return false;
        }

        //来到这里说明该字符串在这三个映射的位置都被设置成1了
        //此时可以认为该字符串是存在的,但是也是会存在误判的
        //想要降低误判率,可以增加每一个字符串映射位置的个数
        //或者增加N,但是凡是都是有两面性的,增加了哈希函数就
        //会在映射时增加计算映射位置的时间,增大N就需要开辟更
        // 多的空间
        return true;
    }
private:
    bitset<N> _bs;
};

2.7 布隆过滤器的优点

  1. 增加和查询元素的时间复杂度为:O(K), (K为哈希函数的个数,一般比较小),与数据量大小无关。
  2. 哈希函数相互之间没有关系,方便硬件并行运算。
  3. 布隆过滤器不需要存储元素本身,在某些对保密要求比较严格的场合有很大优势。
  4. 在能够承受一定的误判时,布隆过滤器比其他数据结构有这很大的空间优势。
  5. 数据量很大时,布隆过滤器可以表示全集,其他数据结构不能
  6. 使用同一组散列函数的布隆过滤器可以进行交、并、差运算。

2.8 布隆过滤器的缺陷

  1. 有误判率,即存在假阳性(False Position),即不能准确判断元素是否在集合中(补救方法:再建立一个白名单,存储可能会误判的数据)
  2. 不能获取元素本身,只能判断元素存不存在。
  3. 不能从布隆过滤器中删除元素。
  4. 如果采用计数方式删除,还是会影响到其他元素,因为可能要删除的元素本身就不存在。

2.9 布隆过滤器的应用场景

在这里插入图片描述
在这里插入图片描述

三、海量数据处理

3.1 布隆过滤器

  1. 给两个文件,分别有100亿个query,我们只有1G内存,如何找到两个文件交集?分别给出精确算法和近似算法。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

3.2 位图应用

  1. 给定100亿个整数,设计算法找到只出现一次的整数?
  2. 给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集?
  3. 位图应用变形:1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数
    这3个问题在上面位图的地方已经解答过了。

3.3 哈希切割

给一个超过100G大小的log file, log中存着IP地址, 设计算法找到出现次数最多的IP地址?
在这里插入图片描述
在这里插入图片描述
与上题条件相同,如何找到top K的IP?如何直接用Linux系统命令实现?
按每一条log file出现的次数建立一个k个元素的小堆,最后这个堆的k个数就是topk的IP,用linux系统指令实现是:

cat log.txt | cut -f1 -d' ' | sort | uniq -c | sort -nr | head -n 1

上述命令按以下步骤执行:

使用cat命令读取日志文件。
使用cut命令提取每行中的第一个字段(即IP地址)。
使用sort命令对IP地址进行排序。
使用uniq -c命令统计每个唯一的IP地址出现的次数。
使用sort -nr命令按照计数的逆序(从高到低)对IP地址进行排序。
使用head -n 1命令选择排序后的第一行(即出现次数最多的IP地址)。
要找到top K的IP地址,您可以将最后一步的命令更改为head -n K,其中K是您想找到的IP地址的数量。

以上就是今天想要跟大家分享的内容啦,你学会了吗?如果感觉到有所帮助,那就点亮一下小心心,点点关注呗,后期还会持续更新C++相关的知识哦,我们下期见!!!!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华为云云耀云服务器L实例评测|零基础基于宝塔部署项目

前言&#xff1a;在这个数字化快速发展的时代&#xff0c;数据已经成为企业最为宝贵的资产之一。如何保护和管理这些数据&#xff0c;同时实现灵活、高效地运用&#xff0c;已经成为企业必须面对的重要问题。而云服务正是解决这一问题的最佳选择。云服务适用于各种规模的企业&a…

性能优化之防抖

方法1&#xff1a;利用lodash库提供的防抖来处理 方法2&#xff1a;手写一个防抖函数来处理 需求&#xff1a;鼠标在盒子上移动&#xff0c;鼠标停止500ms之后&#xff0c;里面的数字才会变化1 方法一&#xff1a;利用lodash库实现防抖 <!DOCTYPE html> <html lang&…

队列(JAVA)

队列&#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff0c;队列具有先进先出的性质。 入队列&#xff1a;进行插入操作的一端称为队尾 出队列&#xff1a;进行删除操作的一端称为队头 在JAVA中队列和栈不同Stack是一个类&a…

Android gradle dependency tree change(依赖树变化)监控实现

文章目录 前言基本原理执行流程diff 报告不同分支 merge 过来的 diff 报告同个分支产生的 merge 报告同个分支提交的 diff 报告 具体实现原理我们需要监控怎样的 Dendenpency 变化怎样获取 dependency Treeproject.configurations 方式./gradlew dependenciesAsciiDependencyRe…

Flume最简单使用

文章目录 一、简介1、定义2、基础架构 二、快速入门1、解压Flume2、案例一&#xff1a;监控端口号3、案例二&#xff1a;将空目录下文件 三、Flume进阶1、Flume事务2、Flume Agent内部原理3、案例一&#xff1a;监控日志4、案例二&#xff1a;多路复用和拦截器适应4.1 原理4.2 …

web:[极客大挑战 2019]Http

题目 点进页面显示为 浏览了这个网站的页面发现没有什么提示信息 查看源代码 发现一个secret.php&#xff0c;点进去访问 点进页面显示为不知道是从如图所示的网址来&#xff0c;所以需要抓包修改Referer头为https://Sycsecret.buuoj.cn Referer必须得在Connection上方&#…

web:[极客大挑战 2019]Havefun

题目 点进页面&#xff0c;页面显示是一只猫&#xff0c;没有其他的提示信息 查看网页源代码&#xff0c;划到最后 这段php代码包含了通过get方式的提交信息 构造payload&#xff1a; http://aaf4c4b5-7bf2-404f-8bf5-f6e97d830b72.node4.buuoj.cn:81/?catdog 即得到flag f…

BUUCTF 不一样的flag

题目&#xff1a;BUUCTF 不一样的flag 看的这个&#xff1a;BUUCTF 不一样的flag_Afanbird的博客 先查&#xff0c;没壳&#xff0c;32位&#xff0c;打开 ida分析&#xff0c;嗯&#xff0c;啥也看不出来&#xff0c;v12345什么的非常混乱 突破口是这两句 发现49是1&#xf…

Ps 在用鼠标滚轮缩放图片时,速度太快?

1.原因 在于安装了第三方鼠标优化软件Mos&#xff0c;它起着对第三方鼠标全局浏览效果的优化&#xff0c;使浏览更加顺滑&#xff0c;而不精确&#xff0c;消除了mac使用第三方鼠标浏览页面时的卡顿问题。这也使得像ps、ai这类软件&#xff0c;在进行页面缩放时&#xff0c;变得…

面向面试知识-消息队列

面向面试知识-消息队列 参考文章&#xff1a;消息队列&#xff08;mq&#xff09;是什么&#xff1f;、重复消费 老坑还没填完&#xff0c;就又开一个新坑&#xff1a; Rocket MQ&#xff1b;Message Queue。 起始问题 为什么引入MQ&#xff1f;MQ适用于哪些场景下的哪些问题…

4 vCPU 实例达成 100 万 JSON API 请求/秒的优化实践

“性能工程” &#xff08;Performance engineering&#xff09;是个日渐流行的概念。顾名思义“性能工程”是包含在系统开发生命周期中所应用的一个技术分支&#xff0c;其目的就是确保满足非功能性的性能需求&#xff0c;例如&#xff1a;性能、可靠性等。由于现代软件系统变…

wifi分销大师小程序v4.0.5独立版saas系统源码+前端

WiFi大师是一款专为商家店内用户设计的WiFi连接小程序。它的出现有效解决了商家在为客户提供WiFi服务的过程中遇到的各种问题&#xff0c;为消费者提供了更加高效快捷的上网方式。 除此之外&#xff0c;WiFi大师小程序还为商家提供了一些额外的功能&#xff0c;例如店铺优惠券…

2023年蓝帽杯取证复现

案件介绍 2021 年 5 月&#xff0c;公安机关侦破了一起投资理财诈骗类案件&#xff0c;受害人陈昊民向公安机关报案称其在微信上认识一名昵称 为 yang88 的网友&#xff0c;在其诱导下通过一款名为维斯塔斯的 APP &#xff0c;进行投资理财&#xff0c;被诈骗 6 万余万元。接警…

84、Redis客户端-->可视化图形界面工具(Another Redis Desktop Manager)的下载、安装及初步使用

Redis客户端–>可视化图形界面工具(Another Redis Desktop Manager)的下载、安装及初步使用 ★ Redis客户端&#xff1a; ▲ Redis自带的命令行工具&#xff08;简陋&#xff09;&#xff1a; CLI工具&#xff0c;重新打开一个命令行窗口&#xff0c;在其中输入如下命令&…

5请求处理流程

产品代码都给你看了&#xff0c;可别再说不会DDD&#xff08;五&#xff09;&#xff1a;请求处理流程 # 这是一个讲解DDD落地的文章系列&#xff0c;作者是《实现领域驱动设计》的译者滕云。本文章系列以一个真实的并已成功上线的软件项目——码如云&#xff08;https://www.…

APP产品经理的主要内容(合集)

APP产品经理的主要内容1 职责&#xff1a; 1.成产品的功能、流程、界面设计&#xff0c;协调设计资源落实产品交互、原型设计; 2.负责产品上线后客户反馈跟踪&#xff0c;并根据产品规划策略和客户反馈优先级落实产品改进设计计划&#xff0c;不断提升竞争力。 3.关注竞争对…

经典网络解析(三)GoogleNet | Inception块,1*1卷积核,辅助分类器 整体结构代码

文章目录 1. 串联结构VGG存在的问题2. GoogleNet结构解析2.1 Inception块2.2 最后采用平均池化操作2.3 辅助分类器 3.代码实现3.1 实现Inception块3.2 各个块依次实现 4 **贡献总结** 之前讲了 AlexNet的解析经典网络(一) AlexNet逐层解析 | 代码、可视化、参数查看&#xff01…

2021 ICPC澳门题解(8/11)

AC情况 赛中通过赛后通过暂未通过A√B○C√D-E√F√G○H-I○J-K√ 整体体验 easy&#xff1a;AKF mid&#xff1a;CEGI hard&#xff1a;DHBJ 心得 整体感觉出的题比较传统&#xff0c;严格的卡精度/卡时间 题解 A. So Ill Max Out My Constructive Algorithm Skills&…

mysql explain学习记录

参考了公司内相关博客&#xff0c;实践并记录下&#xff0c;为后面分析并优化索引做准备。 MySQL explain命令是查看MySQL查询优化器如何执行查询的主要方法&#xff0c;可以很好的分析SQL语句的执行情况。 每当遇到执行慢&#xff08;在业务角度&#xff09;的SQL&#xff0c;…

LeetCode 75-02:字符串的最大公因子

前置知识&#xff1a;使用欧几里得算法求出最大公约数 func gcdOfStrings(str1 string, str2 string) string {if str1str2 ! str2str1 {return ""}return str1[:gcd(len(str1), len(str2))] }func gcd(a, b int)int{if b 0{return a}return gcd(b, a%b) }