有限内存存储数亿级的数据

147 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第11天,点击查看活动详情

问题

问题1:某个名单有很大的数据量,你要如何存储?使用场景:有一个接口需要判断某用户是否存在与该名单内。

方案:此问题的关键点是对名单的存储,首先想到的是缓存,直接使用 Redis 使用 hash 或者 set 的数据结构进行存储将 名单用户唯一标识 userId 作为 key 进行存储。这样我们仅需读取缓存,并判断某个 userId 是否存在即可。

问题2:如果不使用 redis 和 数据库 那如何存储?

方案:如果直接加载到内存中,那么将是很大浪费的系统内存,而且也需要很大内存的机器去处理,不仅是耗时也是浪费资源的操作。

使用数据结构 Bitmap 解决。

Bitmap

这里 BitMap 时指一种数据结构,通过一个 bit 数组存储特定数据的,而不是图片存储格式。bit 时数据的最小单位,所以存储时可以节省空间。

场景:记录员工的考勤,通过构造一个和员工相同数量的 bit 数组,每个位置对应一个员工,若员工正常出勤为1 ,否则为 0 ,这样就可以使用 bit 数组保存当天的考勤记录。

使用 bitmap 进行存储时,也方便通过位运算,对数据进行处理。

场景:若想知道近两天都没正常出勤的员工,仅需将昨天的 bitmap 和今日 bitmap 进行按位 OR 计算,若计算为 0 ,那说明该位置的员工两天没出勤。

所以,bitmap 其实就是一种数据结构,bit 数组的结构。

  • 节省空间
  • 方便按位运算

回到最初的问题,如何存储数亿级的数据?

解决方案

方案1:名单的用户都分配一个自增量的用户唯一标识,如1,2,...100,然后映射到 Bitmap中依次索引位置。此自增量方式,Bitmap 的长度也随着用户数据量增长和减少,有多少用多少,不浪费。

方案2:计算名单用户的 hash,如 MD5,如果生成的数字长度很大,而bitmap 无需使用这么大空间,可以再进行一个取余数的映射到 bitmap。这种固定规则计算映射方式就不像方案1,要先进行数据量查询。但存在问题,如取余数映射可能发生位置冲突的情况,将导致所存储数据不可信。