前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Fourinone-4.17.10 新版本发布​:单机毫秒完成上亿大数据常规统计

Fourinone-4.17.10 新版本发布​:单机毫秒完成上亿大数据常规统计

作者头像
企鹅号小编
发布2018-01-26 16:12:48
7390
发布2018-01-26 16:12:48
举报
文章被收录于专栏:云计算云计算云计算

Fourinone-4.17.10 新版本内容:

虽然现在最火的是 AI,但是大数据和计算能力仍然是机器学习 /AI 算法的重要支撑,我们的业务场景大部分是通过手机终端、服务器日志不断产生日志数据,通过消息通道发送到大数据平台进行存储、加工和统计,然后在统计数据之上提供算法挖掘用户偏好行为和画像,为此,我们的关键任务是需要从海量数据里统计分析每项产品的去重用户、新增用户、pv、uv、dau(日活)、mau(月活)等指标,这个过程存储占用越少,计算时间越快越好。Fourinone(CoolHash) 拥有原创数据库引擎设计能力和知识产权,能够在引擎层面灵活扩充各种功能支持,为了提供大数据统计计算的最优解决方案,4.17 在引擎上增强了以下特性:

1

增加了自加和存在新增两个原子操作

1、Object putPlus(String key, T plusValue)

如果 key 对应的 value 是数字类型(int、long、double、float),自增加 plusValue(数字类型),如 plusValue=1,表示每次自增 1,plusValue 也可以是小数。如果 key 对应的 value 是字符串类型,自增加 plusValue(字符串),会累加到原字符串后面,可以用分隔符隔开。putPlus 的返回值为该 key 的上一个值。

2、Object putNx(String key, T value)

如果 key 存在,则不操作,如不存在写入 value。putNx 返回值为 key 操作前值,为 null 表示不存在,否则返回已有值。

利用 putPlus 和 putNx 可以完成很多原子操作,如 count 类计数统计,在开源包指南附带的 CountDemo.java 里的 countTest 方法演示了 putPlus 的使用,在 ThreadClient.java 的 putPlusTest 方法和 putNxTest 方法演示了多线程下的使用。

pvTest 方法演示了计算 pv,如果 id 不存在则写入,并将 pv 数自加 1,其他线程发现 id 存在,则无法更新 pv 数

2

增加了客户端本地和存储引擎端强大的 bitmap 支持

上面通过 putPlus 和 putNx 原子操作可以计算 pv,但并不是最高效的方案,使用 bitmap 有两个非常显著的优势:位存储占用空间低,位计算效率高。将需要做统计计算的 id 转换成数字序号,每个只占 1 个 bit,对于 20 亿的用户 id,只需要 20 亿 bit 约 238m 大小,压缩后占用空间更小,最少只要 200k;通过单个 bitmap 可以完成去重操作,通过多个 bitmap 的且、或、异或、反等位操作可以完成日活、月活、小时分钟活跃、重度用户、新增用户、用户流向等绝大部分的统计计算,而且能在单机毫秒级完成,真正做到实时计算出结果,同比 hadoop/hive 离线计算执行“select distinct count…from…groupby join…”类似 sql 的方式统计,往往需要几百台机器,耗用 30 分钟才能完成,对比非常悬殊,而且容易形成大量 sql 任务调度和大表 join 给集群带来繁重压力。

1、去重用户:求 1 的总数

2、活跃用户: 取或

bitmap1 | bitmap2

3、非活跃用户:取反:

~bitmap1

4、重度用户:取且:

Bitmap1 & bitmap2

5、新增用户:取或加异或:

(Bitmap1 | bitmap2)^bitmap1

6、多种指标组合:

Bitmap1 & bitmap2 & bitmap3 &…

等等

同时提供 bitmap 本地和引擎端互通实现,能够进行更灵活的架构设计,可以将 bitmap 压缩存储到任何数据库上,客户端拉回后完成聚合计算,计算完成的结果再写回数据库。也可以多个客户端同时连接到 CoolHash 存储引擎上,通过引擎的 bitmap 操作支持完成去重、聚合、解压缩等支持。BitMap 结合存储引擎如下图:

1、本地内存实现,CoolBitSet 实现了以下 bitmap 功能:

CoolBitSet(int maxSize),可指定大小限制,默认 1000 万大小,本地没有最大限制,可以使用多个分区的 bitmap 表示整型范围或长整型范围的数据,每个 1000 万的 bitmap 压缩后在 2m 以内,很适合放入 kv 存储。

基本操作:CoolBitSet 提供基本的 get(int n)、set(int n)、put(int n) 操作,其中 put 为存在返回 get,不存在 set,除外还提供批量操作:int set(CoolBitSet cbs): 将另外一个 bitmap 对象合并到当前 bitmap,并返回新增的数量。

聚合操作:求且、求或、异或、求反、求新增

CoolBitSet and(CoolBitSet cbs):两个 CoolBitSet 求且,更新到当前对象,并返回该对象引用

CoolBitSet or(CoolBitSet cbs):两个 CoolBitSet 求或,同上

CoolBitSet xor(CoolBitSet cbs):两个 CoolBitSet 求异或,同上

CoolBitSet andnot():将该 CoolBitSet 对象求反,同上

CoolBitSet setNew(CoolBitSet cbs):求当前 CoolBitSet 的新增用户,并返回新增用户结果的对象引用

求总数:int getTotal() 返回该 CoolBitSet 的用户总数,bit 位是 1 的总数量

求容量:int getSize() 返回该 CoolBitSet 的容量大小

调试查看:String toString(int num) 返回该 CoolBitSet 的二进制字符串,为了减少长度,参数 num 为需要查看的 byte 数,如 num=5 表示查看前 5 个 byte 的二进制串

和 java 的 bitmap 的实现区别:jdk 自带的 BitSet 类是以 long 数组实现,而且只能初始化大小,无法限制大小,每个 bitset 要耗用几百 m 的内存,多个 bitmap 容易造成空间大量浪费,BitSet 类只是本地内存实现,没有分布式存储引擎持久化支持。

2、引擎端持久化实现,CoolHashClient 提供了以下接口用来操作存储引擎:

int putBitSet(String key, int index):

单项操作,类似 CoolBitSet 的 put,第一个参数为 bitmap 的 key,第二个参数将该 bitmap 的 index 位置设为 1。

boolean getBitSet(String key, int index):

单项操作,类似 CoolBitSet 的 get,第一个参数为 bitmap 的 key,第二个参数需要获取的 index 位置的值。

int putBitSet(String key, CoolBitSet cbs):

批量操作,类似 CoolBitSet 的批量 set,将另外一个 bitmap 对象合并到指定 key 的 bitmap,并返回新增的数量。获取 CoolBitSet 对象仍然使用 get 接口 Object get(String key)

Object putBitSet(String key, CoolBitSet cbs, String logical):

聚合操作,参数 logical 可以设置为“and”,“or”,“xor”,“andnot”,”new”之一,对于“andnot”,参数 cbs 并不起作用,可以传入任意不为空的 CoolBitSet 对象。聚合操作会作用到该 key 指定的 bitmap 上,返回值为聚合后的 CoolBitSet 对象。

以上操作遵循 CoolHash 的 k/v 存储约束,k 为字符串,v 不超过 2m(可修改默认配置大小)。注意 CoolBitSet 对象可以用三种方式进行 k/v 存储和压缩:

存储为 bitSet 格式,合并数据:putBitSet(String key, CoolBitSet cbs)

存储为 bitSet 格式,直接覆盖:put(String key, CoolBitSet cbs)

普通 kv 存储格式,非 bitSet 格式:put(String key, cbs.getBytes());由于是对象存储,三种 put 方式都会对 value 数据进行压缩,采用压缩率和耗时比较平衡的 gzip 压缩。前两种 bitSet 格式存储方式,会验证 CoolBitSet 大小不能超过 1 亿,否则不能提交。第三种普通 kv 存储格式,没有 1 亿的限制,只要压缩后大小不超过 2m,可以正常提交,但由于不是 CoolBitSet 格式,存储引擎无法识别做聚合等操作。

和 redis 的 bitmap 的实现区别:redis 实现了 bitmap 的单项操作和聚合操作,但是没有批量操作,也没有压缩,通过 offset 指定偏移量的方式分配空间容易造成浪费。

开源包指南附带 CountDemo.java 里的演示:

bitSetTest 方法:先演示了全量存储,写入 10 亿数据到 1 个 bitmap,耗时不到 1 秒;再演示了分区存储,将 1 亿大小的数据分成 10 个 1000 万大小的 bitmap 存储。

realtimeStatistics 方法:演示基于 bitmap 做用户去重、活跃用户、非活跃用户、重度用户、新增用户等实时计算

retainLocal 方法和 retainServer 方法:分别演示了如何使用本地内存和存储引擎计算用户留存

3、增加 String 类型的 bitmap 支持:StringBitMap 实现了 String 类型的 bitMap,通过对 hash 算法的改进,能够做到 1 亿字符串数据只有 200 多的碰撞率,5000 万内数据几乎没有碰撞率,对于不超过 1 亿的数据是很合适的,但 1 亿以上的字符串数量仍然不合适,碰撞率会大幅上升。开源包指南附带 CountDemo.java 里的 stringBitMapTest 方法演示了模拟 1000 万随机生成的 15 位 IMEI 设备号,并返回碰撞个数。

4.17.10 版本同时提供 jdk1.8.0_151 编译下"fourinone.jar"包和 jdk1.7.0_80 编译下"fourinone-jdk7.jar"包。4.17.10 版本更新 github code 和 gitee code,本版本所有开源内容已经进行了公司报备,感谢领导对开源的支持。

https://github.com/fourinone/fourinone

https://gitee.com/fourinone/fourinone

本文来自企鹅号 - InfoQ媒体

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文来自企鹅号 - InfoQ媒体

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档