八股收录:如何实现10亿数据判重?

当数据量比较大时,使用常规的方式来判重就不行了。

例如,使用 MySQL 数据库判重,或使用 List.contains() 或 Set.contains() 判重就不可行,因为 MySQL 在数据量大时查询就会非常慢,而数据库又是及其珍贵的全局数据库资源。

《阿里巴巴Java开发手册》上也说了,如果单表数据量超过 500 万或 2GB 时就建议分库分表了,如下图所示:

alt

所以数据库去重显然是不行的。而使用集合也是不合适的,因为数据量太大,使用集合会导致内存不够用或内存溢出和 Full GC 频繁等问题,所以此时我们的解决方案通常是采用布隆过滤器来实现判重,布隆过滤器的详情请访问:如何实现布隆过滤器?其中,推荐使用 Redis 中的布隆过滤器来实现大数据量的判重。

知识扩展

除了布隆过滤器之外,我们还可以使用 BitMap(位图)的数据类型来实现判重。

位图(BitMap)是一种数据结构,用于表示一个特定范围内的元素是否存在或者某种状态,通常用二进制位来表示。在位图中,每一个位只能是 0 或 1,分别表示元素不存在或存在。位图通常用一个 bit 数组来实现,每个 bit 位对应一个元素,如下图所示:

alt

其中,上图中的 1 表示有值,上面 BitMap 描述的值是 1,3,5。

BitMap 优点分析

位图的优势包括:

  1. 空间效率优势:位图极大地节省了存储空间。对于大量稀疏数据,特别是当元素数量远大于实际存在的项时,相比于使用传统的列表、集合等数据结构,位图占用的空间极小。
  2. 查询速度:由于内存访问是按字节或字进行的,因此对单个元素的存在性检查时间复杂度为 O(1),即常量时间,非常快速。
  3. 批量操作高效:对于批量插入、删除和查询操作,尤其是统计某一范围内元素的数量,位图表现出优秀的性能。

BitMap VS int

以 Java 中的 int 为例,来对比观察 BitMap 的优势,在 Java 中,int 类型通常需要 32 位(4 字节*8),而 BitMap 使用 1 位就可以来标识此元素是否存在,所以可以认为 BitMap 占用的空间大小,只有 int 类型的 1/32,所以有大数据量判重时,使用 BitMap 也可以实现。

PS:布隆过滤器的底层就是基于 BitMap 数据结构实现的。

BitMap 在 Java 中的使用

BitMap 在 Java 中的具体实现是 java.util 中的 BitSet,BitSet 是一个可变大小的位向量,能够动态增长以容纳更多的位数据,以下是 BitSet 基本使用示例:

import java.util.BitSet;

public class BitmapExample {
    public static void main(String[] args) {
        // 创建一个BitSet实例
        BitSet bitmap = new BitSet();

        // 设置第5个位置为1,表示第5个元素存在
        bitmap.set(5);

        // 检查第5个位置是否已设置
        boolean exists = bitmap.get(5);
        System.out.println("Element at position 5 exists: " + exists);  // 输出: Element at position 5 exists: true

        // 设置从索引10到20的所有位置为1
        bitmap.set(10, 21);  // 参数是包含起始点和不包含终点的区间

        // 计算bitset中所有值为1的位的数量,相当于计算设置了的元素个数
        int count = bitmap.cardinality();
        System.out.println("Number of set bits: " + count);

        // 清除第5个位置
        bitmap.clear(5);

        // 判断位图是否为空
        boolean isEmpty = bitmap.isEmpty();
        System.out.println("Is the bitset empty after clearing some bits? " + isEmpty);
    }
}

课后思考

除了布隆过滤器和 BitMap 之外,还有哪些大数据量判重的实现方案呢?布隆过滤器实现判重的原理又是啥呢?

参考 & 鸣谢

《阿里巴巴Java开发手册》

javacn.site

#八股文##java学习#
Java面试精讲 文章被收录于专栏

Java常见面试题、场景题、企业真题精讲。

全部评论

相关推荐

03-13 13:58
已编辑
小红书_后端开发
压力有点大,三四个面试官交叉面在公司的持久化方法中,你了解AOF和ROF这些原理吗?你对MySQL的原理了解吗?比如回表是什么意思?对于TCP协议中的黏包和滑动窗口机制,你有何了解?你是否写过基于TCP的示例程序,对TCP内部机制了解多少?操作系统层面的内存管理中,虚拟地址和物理地址有何区别?是否使用过top命令查看内存占用情况,能否区分虚拟地址和物理地址?你是否有编写多线程程序的经验,能否解释一下什么是死锁以及如何避免?读写锁的特点是什么?对于分布式原理,尤其是强同步、常同步和异步同步,你了解过吗?是否了解过分布式一致性协议?在分布式系统中,如何保证全局一致性或通过分布式锁实现原子性操作?两阶段提交协议是什么?ai agent的工作原理是什么?与大模型通信的部分是由你写的吗?对于大语言模型内部的系统提示词和助手提示词有何了解?大模型的历史记录是如何实现的?在小红书的应用中,对大模型进行提示词压缩以降低token消耗的情况是如何处理的?在数据库服务平台的建设中,你遇到过哪些难以解决的问题,又是如何解决的?你如何看待数据库服务平台与你在小红书做的xxAI工作台这两个项目的不同之处?对于未来个人发展规划,你有什么想法?在工作中,对数据库的依赖程度如何?是否在个人环境尝试部署过MySQL或Redis等数据库?问实习,然后从实习接入又开始问八股了:在第一份工作或实习经历中,如何优化数据库查询性能?是否经历过根据自然语言生成查询语句的数据库查询服务开发?你这边是如何实现对接多个数据库的查询服务的?RAG中的向量库使用了什么技术?搜索服务是如何实现的?你对数据库操作熟悉到什么程度?能否举例说明MySQL重命名操作的指令?是否了解数据库同步技术,比如数据同步或数据库集群同步?对于Mongo、Redis等数据库的哨兵模式和分片集群架构是否了解?是否了解Raft协议及其在数据库中的应用?反问:IEG平台上的角色有哪些?答:在IEG平台上,平台上有平台开发的角色,大部分以DBA为主,但也包含开发角色,由专门的Java开发人员配合DBA进行一些监控和其他平台相关工作。平台上的DBA通常自行编写与底层操作相关的代码,而非前端或其他部门来完成,因为这些操作需要专业能力。整个数据库平台是如何构建的?答:整个数据库平台有分层结构,产品经理负责原型设计,产品设计师设计完成后交由前端开发人员实现。同时,数据库相关的存储、内核开发以及平台开发等也是重要组成部分,要求团队成员具备较强多面能力。面试官问:目前是否有offer,以及对中间件部分的理解?目前有一些在上海的offer。在中间件部分,各个团队都有组件开发人员负责数据库内核定制等工作,例如数据库proxy的开发。
点赞 评论 收藏
分享
评论
1
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务