随着闲鱼业务的发展,用户规模达到数亿级,用户维度的数据指标,达到上百个之多。数据库
如何从亿级别的数据中,快速筛选出符合指望的用户人群,进行精细化人群运营,是技术须要解决的问题。业界的不少方案经常须要分钟级甚至小时级才能生成查询结果。性能优化
本文提供了一种解决大数据场景下的高效数据筛选、统计和分析方法,从亿级别数据中,任意组合查询条件,筛选须要的数据,作到毫秒级返回。架构
技术选型分析并发
从技术角度分析,咱们这个业务场景有以下特色:高并发
综合分析,这是一个典型的 OLAP 场景。性能
OLTP 与 OLAP学习
下面简单对比下 OLTP 和 OLAP:大数据
最多见的数据库,如 MySQL、Oracle 等,都采用行式存储,比较适合 OLTP。优化
若是用 MySQL 等行数据库来实现 OLAP,通常都会碰到两个瓶颈:设计
综上分析,咱们的应用场景,并不适合采用行存储数据库,所以咱们重点考虑列存数据库。
行式存储与列式存储
下面简单对比一下行式存储与列式存储的特色:
行存适合近线数据分析,好比要求查询表中某几条符合条件的记录的全部字段的场景。
列存适合用于数据的统计分析。考虑以下场景:一个用于存放用户的表中有 20 个字段,而咱们要统计用户年龄的平均值,若是是行存,则要全表扫描,遍历全部行。
但若是是列存,数据库只要定位到年龄这一列,而后只扫描这一列的数据就能够获得全部的年龄,计算平均值,性能上相比行存理论上就会快 20 倍。
而在列存数据库中,比较常见的是 HBase。HBase 应用的核心设计重点是 rowkey 的设计,通常要把经常使用的筛选条件,组合设计到 rowkey 中,经过 rowkey 的 get(单条记录) 或者 scan(范围) 查询。
所以 HBase 比较适合有限查询条件下的非结构化数据存储。而咱们的场景,因为全部字段都须要做为筛选条件,因此本质上仍是须要结构化存储,且要求查询低延迟,所以也没法使用 HBase。
咱们综合考虑集团内多款列式存储的 DB 产品(ADS/PostgreSQL/HBase/HybridDB)。
综合评估读写性能、稳定性、语法完备程度及开发和部署成本,最终选择了 HybridDB for MySQL 计算规格来构建人群圈选引擎。
HybridDB for MySQL 介绍
HybridDB for MySQL 计算规格对咱们的这个场景而言,核心能力主要有:
那么,HybridDB for MySQL 计算规格是如何作到大数据场景下的任意维度组合查询的毫秒级响应的呢?
步骤以下:
综合来讲,HybridDB for MySQL 计算规格是以 SQL 为中心的多功能在线实时仓库系统,很适合咱们的业务场景,所以咱们在此之上构建了咱们的人群圈选底层引擎。
业务实现
在搭建了人群圈选引擎以后,咱们重点改造了咱们的消息推送系统,做为人群精细化运营的一个重要落地点。
闲鱼消息推送简介
消息推送(PUSH)是信息触达用户最快捷的手段。闲鱼比较经常使用的 PUSH 方式,是先离线计算好 PUSH 人群、准备好对应 PUSH 文案,而后在次日指定的时间推送。
通常都是周期性的 PUSH 任务。可是临时性的、须要马上发送、紧急的 PUSH 任务,就须要 BI 同窗介入,每一个 PUSH 任务平均约须要占用 BI 同窗半天的开发时间,且操做上也比较麻烦。
本次咱们把人群圈选系统与原有的 PUSH 系统打通,极大地改善了此类 PUSH 的准备数据以及发送的效率,解放了开发资源。
系统架构
离线数据层:用户维度数据,分散在各个业务系统的离线表中。咱们经过离线 T+1 定时任务,把数据汇总导入到实时计算层的用户大宽表中。
实时计算层:根据人群的筛选条件,从用户大宽表中,查询符合的用户数量和用户 ID 列表,为应用系统提供服务。
人群圈选前台系统:提供可视化的操做界面。运营同窗选择筛选条件,保存为人群,用于分析或者发送 PUSH。
每个人群,对应一个 SQL 存储,相似于:
- select count(*) from user_big_table where column1> 1 and column2 in ('a','b') and ( column31=1 or column32=2)
同时,SQL 能够支持任意字段的多层 and/or 嵌套组合。用 SQL 保存人群的方式,当用户表中的数据变动时,能够随时执行 SQL,获取最新的人群用户,来更新人群。
闲鱼 PUSH 系统:从人群圈选前台系统中获取人群对应的 where 条件,再从实时计算层,分页获取用户列表,给用户发送 PUSH。在实现过程当中,咱们重点解决了分页查询的性能问题。
分页查询性能优化方案:在分页时,当人群的规模很大(千万级别)时,页码越日后,查询的性能会有明显降低。
所以,咱们采用把人群数据增长行号、导出到 MySQL 的方式,来提高性能。
表结构以下:
咱们为"人群 ID"+"批次号"+"行号"建组合索引,分页查询时,用索引查询的方式替换分页的方式,从而保证大页码时的查询效率。
另外,为此额外付出的导出数据的开销,得益于 HybridDB 强大的数据导出能力,数据量在万级别至百万级别,耗时在秒级至几十秒级别。综合权衡以后,采用了本方案。
PUSH 系统改造收益
人群圈选系统为闲鱼精细化用户运营提供了强有力的底层能力支撑。同时,圈选人群,也能够应用到其余的业务场景,好比首页焦点图定投等须要分层用户运营的场景,为闲鱼业务提供了很大的优化空间。
本文实现了海量多维度数据中组合查询的秒级返回结果,是一种 OLAP 场景下的通用技术实现方案。
同时介绍了用该技术方案改造原有业务系统的一个应用案例,取得了很好的业务结果,可供相似需求或场景的参考。
感兴趣的能够本身来个人Java架构群,能够获取免费的学习资料,群号:855801563对Java技术,架构技术感兴趣的同窗,欢迎加群,一块儿学习,相互讨论。