唯品金融大数据团队的图数据库实践
1
风控与图
在大数据时代,社交关系趋于复杂化,越来越多的互联网项目都和社交关系联系起来。而对社交关系的良好契合,使得图数据库(Graph Database)在互联网领域迅速崛起。通过图数据库可以高效地进行社交关系查询、分析和数据挖掘,以发现有价值的信息。
近几年互联网金融发展火热,用户对消费分期、现金贷等需求也越来越高。然而机遇也意味着调挑战,相比传统金融行业,互联网金融由于申请流程简化,更容易遇到恶意套现、骗贷、拖欠后失联等情况。如何识别欺诈行为,减少坏账,是互联网金融行业首要解决的问题。
唯品金融开始着手唯品花等金融业务后,也逐步将人群关系应用于风控反欺诈和失联管理等之中。
反欺诈是风控中的重要环节,下面我们来看一下基于图数据库怎么进行反欺诈。将一个新申请用户的手机号、银行卡号、身份证号等信息放到现有的图中进行查询, 如果在1度或2度关系内连接到欺诈用户相同手机号或者银行卡号,我们判断这个用户是欺诈用户的可能性很大。
失联管理属于贷后风控,借款人如果在借钱以后失联,我们可以利用图数据库搜索跟这个人有关系的其他联系人,从而联系到失联客户。
2
图数据库VS关系型数据库
关系型数据库RDBMS经过几十年的发展,出现了不少该领域的经典产品,如Oracle、MySQL和SQLServer。如今关系型数据库虽然依旧在存储领域处于统治地位,但是随着互联网大数据的发展,也暴露出一些它无法很好解决的问题:
比如处理复杂社交关系,关系型数据库需要建立大量关系表,来表达实体和实体之间关系,每层关系在查询时就需要join一次关系表。
图数据库和关系型数据库的不同,是可以将社交关系等数据描述为点(Vertex ) 和 边 (Edge)及他们的属性(Property),每一张图(Graph)都可以看做是一个结构化数据。
关系型数据库在表示两个实体之间的关系时,就要创建关联表。 而需要表示多个关系时就要创建多关联表,这些关联表不记录信息,仅仅用来表示关系。而在图数据库中,仅需要标明两个实体间的关系:data1->relation->data2。
在做关联分析时关系型数据库一旦会涉及到多个关系表,做联表查询需要运行很长时间,但是图数据库就会非常快速,因为基于图的高效遍历算法,只需运行几秒甚至几毫秒就能得出结论,速度上有数量级的提升。
3
图数据库的选择
目前主流图数据库有neo4j,orientdb, janusGraph/Titan等。
2018年2月的graph db排名
参见:https://db-engines.com/en/ranking/graph+dbms
neo4j是老牌的高性能图数据库,拥有最多的用户群体。neo4j允许用户通过其特有的Cypher语言来操作数据库,Cypher语言是专为图数据库设计的,可以非常高效地对数据库实例进行操作。单个neo4j实例可以存储数十亿节点和边,十字链表结构在内存足够大时性能非常不错,查找一个点的边或者边上的端点时,不需要再走一次B+树索引,而是直接指针指向下一度的物理地址。然而neo4j不支持分布式存储,集群也只是通过read replica进行读写分离,对于单机内存无法支持的数据量读写性能会急剧下降。
JanusGraph/Titan是一个分布式图形数据库,特别为处理大规模图而设计。通过使用第三方nosql存储(HBase,Cassandra等)来实现分布式读写,插件式索引架构可以使用 elasticsearch,solr等来建索引,接口上支持Tinkerpop Gremlin。由于底层接口都是用第三方开源实现,只是在分布式nosql上封装了一层图处理的逻辑,存储和查询严重分离,查询性能上有很大的提升的空间。依赖第三方的实现使JanusGraph的使用和维护成本也较高。
Orientdb 是目前发展较快的一个图数据库, 社区非常活跃。Orientdb的特点是轻量级,采用源生存储和索引,支持ACID事务, 支持multi-master 分布式读写,接口方面支持SQL查询, Tinkerpop Gremlin等多种开发接口,使程序员能很快上手。缺点是当前2.X版本是在大数据量的情况下还不够稳定。
唯品金融大数据团队最终选择了Orientdb作为金融风控的图数据库,不过在开发使用过程中Orientdb 坑也很多, 我们也在github上提了一些bug。
比如底层btree分裂时的null point exception的问题,参见:
https://github.com/orientechnologies/orientdb/issues/7897
4
OrientDB存储结构和缓存
OrientDB的高效数据读写依赖于其使用的SBTree结构,是一种基于B+树的实现,非叶子节点之间前后都有链接,在数据被删除时不会删除节点, 而是在新增节点时复用,优化了数据插入和范围查询。
树的Key由一个short型的clusterId和一个long型clusterPostion的组成, 像#21:84730,表示clusterId为21, clusterPostion为84730。
OrientDB本地存储引擎称为plocal engine,plocal engine基于以下原则实现: 磁盘数据被分割为固定大小的页面(page),单个page的操作为原子操作。任何数据变化在刷新到磁盘前都会先写入WAL日志,即便变化没有写入到磁盘服务器就崩溃了,数据也能从WAL日志恢复。
新版本的plocal引擎不再使用系统的MMAP作为缓存,而是有自己的缓存解决方案来控制缓存的生命周期, 它把缓存分为read cache和write cache。大大改善了大数据量情况下性能下降的问题,参见:https://github.com/orientechnologies/orientdb/issues/1202
参见:
https://orientdb.com/docs/2.2.x/plocal-storage-engine.html
https://github.com/orientechnologies/orientdb/issues/1202
5
基于Gremlin和SQL的查询
Orientdb提供了大量的接口, 其中最常用的就是Gremlin和sql。
Gremlin是Apache TinkerPop 框架下的图遍历语言。Gremlin是一种函数式数据流语言,可以使得用户使用简洁的方式表述复杂的图的遍历或查询,大部分图数据库都支持Gremlin。示例图总共拥有12个节点(Vertex) 11条边(Edge)。
第1条命令g.V().has('uid', 1)表示查询字段uid的值为1的节点ID
gremlin> g.V().has('uid', 1)
==>v(user_id)[#21:0]
第2条命令g.v('21:8').outE('phone_use')表示查询节点ID为#21:8的 类型为phone_use,方向为OUT的边
gremlin> g.v('21:0').outE('phone_use')
==>e[#53:0][#21:0-phone_use->#33:0]
==>e[#56:0][#21:0-phone_use->#35:0
OrientDB支持类SQL查询,只要熟悉SQL的开发人员很容易就能上手,与上面Gremlin命令等价的SQL:
SQL | Gremlin |
select @rid, @class from V where uid = 1 | g.V().has('uid', 1) |
select expand(OUTE('phone_use')) from #21:0 | g.v('21:0').outE('phone_use') |
orientdb {db=graph}> select @rid, @class from V where uid = 1
+----+-----+-------+
|# |rid |class |
+----+-----+-------+
|0 |#21:0|user_id|
+----+-----+-------+
orientdb {db=graph}> select expand(OUTE('phone_use')) from #21:0
+----+-----+---------+-----+-----+
|# |@RID |@CLASS |out |in |
+----+-----+---------+-----+-----+
|0 |#53:0|phone_use|#21:0|#33:0|
|1 |#56:0|phone_use|#21:0|#35:0|
+----+-----+---------+-----+-----+
6
OrientDB批量写入优化
唯品金融在使用Orientdb的开发过程中遇到的最大问题,是数据库初始化时的批量写入速度较慢, 由于Vertex和Edge数量在10亿数量级,在没有优化的情况下,单台服务器写入完整数据需要几天。
经过下列优化后,写入速度得到明显改善:
尽量增加磁盘缓存storage.diskCache.bufferSize的大小可以大大提高写入速度
声明大量写入db.declareIntent( newOIntentMassiveInsert() );
关闭WAL日志-storage.useWAL=false,写速度提升1倍以上,写完后再打开WAL
edge边写入时尽量保持同一类型的边一起写,可以减少磁盘缓存的使用
并发写入时,每个线程独立从OrientGraphFactory获取连接,而不是共用一个连接,因为从OrientGraphFactory获取的连接是单个连接,而不是线程池
并发写入时遇到ONeedRetryException属于正常现象,重试即可
参见:
https://orientdb.com/docs/2.2.x/Performance-Tuning.html
优化后Vertex单机写入速度在优化后达到3万/秒, Edge单机写入速度达到1万/秒。
7
总结
唯品金融对图数据库的应用还刚刚起步, 目前已经在识别黑户等反欺诈领域发挥了一定的作用。不过随着数据量和业务复杂度的增加, 我们还会面临更多的挑战。
总的来说,目前图数据库还处在发展的初级阶段,主流图数据库各有优势和缺点,暂时还没有哪个图数据库可以在功能和性能上明显领先其他图数据库。这两年图数据库被使用的越来越多,开源社区也很活跃。但整体而言,图数据库还有很多问题未解决,许多技术还需发展,比如深度关联的实时查询效率,分布式大规模图的存储。
可以预见的是,随着互联网大数据的发展,基于的社交关系的业务应用也会越来越多,图数据库必将迎来高速的发展。