美图分布式Bitmap实践:Naix

本文介绍了美图如何利用分布式Bitmap系统Naix处理海量用户数据,优化计算效率和存储空间。Naix是美图自主研发的分布式Bitmap服务,解决了数据存储、序列化和查询性能等问题,支持多维度计算,适用于大数据场景。文章详细阐述了Bitmap的基本原理、美图的Bitmap应用,以及Naix系统设计和未来展望。
摘要由CSDN通过智能技术生成

大数据技术和应用系统目前已经在各个行业中发挥着巨大的作用,各种各样的开源技术也给大数据从业人员带来了很大的便利。Bitmap 作为一种大数据需求下产生的计算体系,有着计算速度快、信息密度高、支持海量数据等众多优势。

美图拥有海量用户数据,每天都有大量数据计算任务。而 Bitmap 技术能大幅度减少计算的开销,节省数据存储的成本,尽管有不少公司做过 Bitmap 的相关尝试,但是到目前为止还没有一个相对成熟的分布式 Bitmap 开源应用,因此美图研发了自己的分布式 Bitmap 系统,应用于美图各个场景下的相关数据计算任务。

 / Bitmap简介 /

Bitmap 作为被各种框架广泛引用的一门技术,它的原理其实很简单。

bit 即比特,而 Bitmap 则是通过 bit 位来标识某个元素对应的值(支持 0、1 两种状态),简单而言,Bitmap 本身就是一个 bit 数组。

举个简单的例子,假设有 10 个用户(ID 分别为 1~10),某天 1、3、5、7、8、9 登录系统,如何简单的表示用户的登录状态呢?如图 1,只需要找到用户对应的位,并置 1 即可。

图 1

更多地,如果需要查看某用户当天是否登录系统,仅需查看该用户 ID 位对应的值是否为1。并且,通过统计 Bitmap 中 1 的个数便可知道登录系统的用户总数。Bitmap 已支持的运算操作(如 AND、OR、ANDNOT 等)可以使维度交叉等计算更加便捷。

Bitmap两个重要的特性

高性能

Bitmap 在其主战场的计算性能相当惊人。在美图,早期的统计主要基于 Hive。以美图系某 APP 数据为基准进行了简单的留存计算(即统计新增用户在次日依然活跃的用户数量),通过 Hive(采用 left out join)耗时 139 秒左右,而 Bitmap(交集计算)仅需 226 毫秒,Hive 的耗时是 Bitmap 的 617 倍左右。如图 2 所示,其中,Hive 基于 4 节点的 Hadoop 集群,而 Bitmap 仅使用单节点单进程。

图 2

存储空间小

由于 Bitmap 是通过 bit 位来标识状态,数据高度压缩故占用存储空间极小。假设有 10 亿活跃设备 ID(数值类型),若使用常规的 Int 数组存储大概需 3.72G,而 Bitmap 仅需 110M 左右。当然,若要进行去重、排序等操作,存储空间的节省带来的性能红利(如内存消耗等)也非常可观。

美图 Bitmap 应用

美图公司拥有众多 APP,如美图秀秀、美颜相机、美拍、美妆相机、潮自拍等。大家熟知的美图秀秀和美颜相机都拥有千万级别的日活,历史累积的用户量更达几十亿。

大部分主要日常统计功能均基于 Bitmap,如新增、活跃、留存、升级、回访等。 同时,我们还支持时间粒度(比如天、周、月甚至年)及 APP、渠道、版本、地区等多种维度,以及各维度的交叉计算等。

图 3

Bitmap 原理简单,但是仅通过 Bitmap 服务来支撑海量数据和需求比想象中更复杂。从 2015 年至今,从单机版到分布式,从单

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`Gdiplus::Bitmap::FromStream` 是 GDI+ 库中的一个函数,用于从流中加载图像。其函数原型如下: ```c++ Gdiplus::Status FromStream( IStream *stream, BOOL useEmbeddedColorManagement = FALSE ); ``` 其中,`stream` 参数是一个指向 `IStream` 接口的指针,用于指定要加载的流对象;`useEmbeddedColorManagement` 参数是一个布尔值,用于指定是否使用嵌入的颜色管理数据。 `Gdiplus::Bitmap::FromStream` 函数返回一个 `Gdiplus::Status` 枚举值,表示加载图像的结果。如果加载成功,返回值为 `Gdiplus::Ok`,否则返回其他错误代码。 使用示例: ```c++ Gdiplus::Bitmap* bmp = NULL; // 图像对象指针 IStream* istream = NULL; // 流对象指针 // 创建流对象 CreateStreamOnHGlobal(NULL, TRUE, &istream); // 将数据写入流 // ... // 从流中加载图像 Gdiplus::Status status = Gdiplus::Bitmap::FromStream(istream, &bmp); // 检查是否成功加载图像 if (status != Gdiplus::Ok || bmp == NULL) { // 加载失败,处理错误 // ... } // 成功加载图像,可以使用 bmp 对象进行绘制等操作 // ... // 释放资源 delete bmp; istream->Release(); ``` 在使用 `Gdiplus::Bitmap::FromStream` 函数加载图像时,需要注意以下几点: - 流对象必须在使用完毕后释放,否则会造成内存泄漏; - 图像对象也必须在使用完毕后释放; - 加载图像时需要检查返回值和图像对象是否为空,避免出现错误。 希望这可以帮助到你。如果你有任何问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值