小微贷款、天使投资(风控助手)业务数据库设计(图式搜索图谱分析) - 阿里云RDS PostgreSQL, HybridDB for PostgreSQL最佳实践

4 minute read

背景

贷款是银行的主营业务之一,但是并不是只有银行能提供贷款,实际上资金雄厚的公司都有能力提供贷款(比如保险行业、资源垄断型企业等)。

pic

除了放贷,我们常说的天使投资、A轮B轮啥的,也是类似的场景,凭什么投你,背后如何决策也需要决策系统的支撑。

pic

与贷款相反的是吸金类业务,比如我们现在发现越来越多的理财产品、股市、甚至是游戏充值,只要是让你存钱,把你的钱留住,而且你还不舍得吧钱取出来的业务,都是吸金类业务。

所以,一些本来就资金雄厚,或者是靠吸金类业务起来的公司,只要吸到足够的金之后,就有放贷款的能力。

放贷本身是一件体力活,来申请贷款的人或企业鱼龙混杂。什么样的人,什么样的企业能获得贷款,需要经过层层审查。审查需谨慎,否则就容易成为放贷公司的烂账。

本文涉及的项目和放贷、审查、风控、舆情系统有关。

一、需求分析

展示企业的图谱信息,例如股权结构、舆情事件、管理层、知识产权,经营状况等。方便审查员查看。

pic

数据的来源,例如爬虫得到的信息、来自合作伙伴(例如招聘网站、税务)的信息等,组成了企业相关的信息网络。

类比社交业务

这类数据和互联网的社交类业务的数据非常类似,A企业投资了B企业(类似微博的LIKE),A企业发布了财报(类似发微博),A企业获得了某个专利。。。。

相关的性能指标:

1、用户数量级1亿(相当于1亿企业名录),好友数量级1~1万(相当于平均每个企业与之相关联的企业1到1万家),单个对象的Like数量1-100万(相当于单个事件被关注的平均次数1到100万次)。

1.1. 关注微博(文章)

17.7万/s,预计可以优化到30万。

1.2. 查询文章被谁like?

101.6万/s

1.3. 查询文章被like了多少次?

104.1万/s

1.4. 查询LIKE某文章的用户中,哪些是我的好友?

64.8万/s

pic

1.5. 机器:

(10W左右价位的X86,12*8TB SATA盘,1块SSD作为BCACHE)

案例详见:

《三体高可用PCC大赛 - facebook\微博 like场景 - 数据库设计与性能压测》

《facebook linkbench 测试PostgreSQL社交关系图谱场景性能》

类比图式搜索业务

企业图谱系统与互联网社交类业务截然不同的地方:

企业数据相对来说是比较静态的数据,所以我们更关注的是查询的性能,按一个企业顺藤摸瓜找出相关企业的数据的性能。与之对应的是下面这个案例,图式搜索的应用。

案例详见:

《金融风控、公安刑侦、社会关系、人脉分析等需求分析与数据库实现 - PostgreSQL图数据库场景应用》

相关的性能指标:

1、1亿企业名录,每5万作为一个有牵连的企业群体,每个企业牵连1000个其他企业,形成1000亿的超大规模关系网。

以某个企业为中心,检索3层关系的企业网络:响应时间15毫秒。

数据量预估

企业:百万。

每个企业相关的关系、舆情事件、财报等,平均预计1000条。

平均每个企业的直接相关企业有50家。

个人(法人、股东、监理、。。。):百万。

每个人有若干家相关企业。

总数据量约10亿级。

二、数据库架构设计

pic

1、相对静态的数据(例如人、企业基本信息、主要成员、股东。。。)

量级:百万。

有些一对多的数据,可以使用数组类型(例如企业主要成员ID、股东ID,存为数组)来存储,从而提升查询效率。

create table corp_info (...);       --  企业相对静态信息  
  
create table people_info (...);     --  个人相对静态信息  

建议将这类静态数据设计为多张表,使用PK关联起来,减少查询少量字段时的数据扫描量(因为PG是行存储格式,查询少量字段时,可以提高命中率减少IO放大)。

2、舆情、流水数据

量级:十亿。

create table corp_feed (corp_id pk, typ int, event);    

3、关系数据

量级:千万 ~ 亿级别。

这个量级基本上不需要考虑存储冗余的正向关系,反向关系,(方便sharding(FDW, hybriddb))。

create table corp_rel (...);  

4、线上线下一体化

阿里云线上的数据,通过逻辑订阅、物理流式复制,可以将数据复制到线下数据库中。

其中逻辑订阅支持表级订阅(每张表的订阅速度约3万行/s,指表在独立订阅通道时)。逻辑订阅还可以通过规则或触发器支持订阅表中的部分数据,甚至实现格式转换等工作。逻辑订阅的备库支持可读可写。(逻辑订阅的大事务延迟比物理复制高)

物理流式复制,支持全库复制,物理复制的好处是延迟低,备库支持只读。

pic

用户建立RDS备库的需求的起因

有些企业因为SOX审计的需求,必须要在自己的机房放一个备节点。

有些企业可能期望通过这种方法建立日常开发或测试环境。

有些架构的需求,例如云端存储所有数据,线下存储部分关心的加速数据。或者云端所有数据拆分成了多个库,分析场景需要将数据合并起来进行分析,那么就有多对一的复制需求,使用PostgreSQL逻辑订阅可以支持。

5、sharding

虽然本文涉及的场景和数据量并不需要sharding(根据后面的测试,实际上RDS PostgreSQL单库支持1000亿数据量,在稳定性、性能各方面应该是没有问题的。),但是考虑到案例的通用性,还是提一下。

可以根据被查询的ID进行切分,如有正反向关系的,可以采用冗余存储的方式达到切片的目的。

PostgreSQL sharding的案例很多:

1、内核层面支持的sharding

《PostgreSQL 9.6 sharding based on FDW & pg_pathman》

2、通过plproxy代理支持的sharding

《PostgreSQL 最佳实践 - 水平分库(基于plproxy)》

3、通过citus插件支持的sharding和mpp

https://github.com/citusdata/citus

4、通过客户端代理支持的sharding

https://github.com/dangdangdotcom/sharding-jdbc

https://github.com/go-pg/sharding/

三、DEMO性能

建表

create table corp_info (  -- 企业信息  
  id int primary key,  -- 企业ID,主键   
  info text,           -- 企业信息  
  core_team int[]      -- 核心团队成员ID  
  -- 忽略其他字段  
);  
  
create table people_info (  -- 人信息  
  id int primary key,  -- 人ID,主键   
  info text,           -- 信息  
  rel_corp int[],      -- 和哪些公司相关  
  rel_type int[]       -- 分别是什么关系(法人、建立、董事长,。。。。)  
  -- 忽略其他字段  
);  
  
create table corp_rel1 (  -- 企业正向关系  
  corp_id1 int,  -- 企业ID  
  corp_id2 int,  -- 企业ID  
  reltypid int   -- 关系类型  
);  
create index idx_corp_rel1 on corp_rel1 (corp_id1);  
  
create table corp_rel2 (  -- 企业反向关系  
  corp_id1 int,  -- 企业ID  
  corp_id2 int,  -- 企业ID  
  reltypid int   -- 关系类型  
);  
create index idx_corp_rel2 on corp_rel2 (corp_id1);  
  
create table corp_event ( -- 企业舆情  
  corp_id int,  -- 企业ID  
  event text,   -- 事件内容  
  crt_time timestamp  -- 时间  
  -- 其他字段略  
);  
create index idx_corp_event_1 on corp_event(corp_id, crt_time desc);  

生成测试数据

生成10.42亿测试数据,数据组成和生成方法如下:

-- 100万 企业数据  
insert into corp_info select generate_series(1,1000000), 'test', array(select (random()*1000000)::int from generate_series(1,20));  
  
-- 100万 人数据  
insert into people_info select generate_series(1,1000000), 'test', array(select (random()*1000000)::int from generate_series(1,20)), array(select (random()*50)::int from generate_series(1,20));  
  
-- 2000万 企业正向关系  
insert into corp_rel1 select random()*1000000, random()*1000000, random()*100 from generate_series(1,20000000);  
  
-- 2000万 企业反向关系  
insert into corp_rel2 select random()*1000000, random()*1000000, random()*100 from generate_series(1,20000000);  
  
-- 10亿 企业舆情  
insert into corp_event select random()*1000000, 'test', now()+(id||' second')::interval from generate_series(1,1000000000) t(id);  

由于数据相对静止,所以我们可以对数据进行cluster话,提高查询效率。(不这么做,实际上也是毫秒级的响应时间,这么做之后可以降低到0.0X 毫秒)

相关案例:

《机票业务性能优化案例 - 阿里云RDS PostgreSQL最佳实践》

cluster corp_rel1 using idx_corp_rel1;  
cluster corp_rel2 using idx_corp_rel2;  
cluster corp_event using idx_corp_event_1;  

压测

1、企业静态数据查询

vi test.sql  
  
\set id random(1,1000000)  
select * from corp_info where id=:id;  
select * from people_info where id = any (array(select core_team from corp_info where id=:id));  
pgbench -M prepared -n -r -P 1 -f ./test.sql -c 64 -j 64 -T 120  
  
transaction type: ./test.sql
scaling factor: 1
query mode: prepared
number of clients: 64
number of threads: 64
duration: 120 s
number of transactions actually processed: 15175162
latency average = 0.506 ms
latency stddev = 0.080 ms
tps = 126454.038435 (including connections establishing)
tps = 126468.912494 (excluding connections establishing)
script statistics:
 - statement latencies in milliseconds:
         0.001  \set id random(1,1000000)
         0.068  select * from corp_info where id=:id;
         0.444  select * from people_info where id = any (array(select core_team from corp_info where id=:id));

2、企业关系数据查询,查询正向和反向关系。

vi test1.sql  
  
\set id random(1,1000000)  
select * from corp_rel1 where corp_id1=:id;  
select * from corp_rel2 where corp_id1=:id;  
pgbench -M prepared -n -r -P 1 -f ./test1.sql -c 64 -j 64 -T 120  
  
transaction type: ./test1.sql
scaling factor: 1
query mode: prepared
number of clients: 64
number of threads: 64
duration: 120 s
number of transactions actually processed: 49723004
latency average = 0.154 ms
latency stddev = 0.032 ms
tps = 414351.413094 (including connections establishing)
tps = 414396.709915 (excluding connections establishing)
script statistics:
 - statement latencies in milliseconds:
         0.001  \set id random(1,1000000)
         0.077  select * from corp_rel1 where corp_id1=:id;
         0.077  select * from corp_rel2 where corp_id1=:id;

3、企业最近10条舆情数据查询

vi test2.sql  
  
\set id random(1,1000000)  
select * from corp_event where corp_id=:id order by crt_time desc limit 10;  
pgbench -M prepared -n -r -P 1 -f ./test2.sql -c 64 -j 64 -T 120  
  
transaction type: ./test2.sql
scaling factor: 1
query mode: prepared
number of clients: 64
number of threads: 64
duration: 120 s
number of transactions actually processed: 94303135
latency average = 0.081 ms
latency stddev = 0.020 ms
tps = 785845.099057 (including connections establishing)
tps = 785941.120081 (excluding connections establishing)
script statistics:
 - statement latencies in milliseconds:
         0.001  \set id random(1,1000000)
         0.081  select * from corp_event where corp_id=:id order by crt_time desc limit 10;

四、达到的效果

1、性能

1.1、企业静态数据查询。

TPS:12.6万

平均响应时间:0.5毫秒

1.2、企业关系数据查询,输出正向和反向关系。

TPS:41.4万

平均响应时间:0.15毫秒

1.3、企业最近10条舆情数据查询。

TPS:78.5万

平均响应时间:0.08毫秒

pic

pic

2、使用阿里云RDS PostgreSQL,用户不需要关心数据库的运维,容灾,备份恢复,扩容,缩容,HA等基本问题,可以更加专注于业务。

3、分析需求,使用PostgreSQL 10提供的多核并行、JIT、算子复用等特性,处理10亿级的数据分析完全不在话下。

《分析加速引擎黑科技 - LLVM、列存、多核并行、算子复用 大联姻 - 一起来开启PostgreSQL的百宝箱》

《TPC-H测试 - PostgreSQL 10 vs Deepgreen(Greenplum)》

4、机器学习需求

阿里云RDS PostgreSQL提供了机器学习插件MADlib,支持Classification, Regression, Clustering, Topic Modeling, Association Rule Mining, Descriptive Statistics, Validation等众多挖掘模型。

pic

http://madlib.incubator.apache.org/product.html

madlib手册

5、线上线下一体化,通过RDS PostgreSQL提供的流复制、逻辑订阅接口,用户可以将数据复制到远端或多个RDS,与业务灵活的组合,实现较灵活的架构(包括多MASTER的支持)。

《使用PostgreSQL逻辑订阅实现multi-master》

《PostgreSQL 10 流式物理、逻辑主从 最佳实践》

6、阿里云云端产品组合拳

使用云端的OSS,HybridDB for PostgreSQL, RDS PostgreSQL,可以支持用户从 流计算、在线业务、数据分析的业务数据闭环。

《打造云端流计算、在线业务、数据分析的业务数据闭环 - 阿里云RDS、HybridDB for PostgreSQL最佳实践》

《ApsaraDB的左右互搏(PgSQL+HybridDB+OSS) - 解决OLTP+OLAP混合需求》

阿里云 RDS PostgreSQL

阿里云 HybridDB for PostgreSQL

五、技术点回顾

本方案用到了哪些技术点:

1、MADlib,支持多种机器学习算法,通过SQL接口调用,实现了数据库的机器学习功能。

2、逻辑订阅,通过逻辑订阅,用户可以复制出多个数据库(可以按表级、行级进行复制),复制出来的SLAVE节点支持读写。

3、物理流式复制,通过物理流式复制,用户可以复制出多个备库,支持只读。

用户建立RDS备库的需求的起因:

有些企业因为SOX审计的需求,必须要在自己的机房放一个备节点。

有些企业可能期望通过这种方法建立日常开发或测试环境。

有些架构的需求,例如云端存储所有数据,线下存储部分关心的加速数据。或者云端所有数据拆分成了多个库,分析场景需要将数据合并起来进行分析,那么就有多对一的复制需求,使用PostgreSQL逻辑订阅可以支持。

4、数组类型,数组类型用于存储一对多的关系,PostgreSQL支持数组的索引检索,效率非常高。

5、SQL 流计算,通过SQL流计算,可以实时的进行数据预警,聚合,转换等操作。在三体高可用PCC大赛中见证了它的卓越效果。

六、云端产品回顾

阿里云 RDS PostgreSQL

阿里云 HybridDB for PostgreSQL

阿里云 OSS

七、类似场景、案例

1、社交类场景业务。

《三体高可用PCC大赛 - facebook\微博 like场景 - 数据库设计与性能压测》

《facebook linkbench 测试PostgreSQL社交关系图谱场景性能》

2、图式搜索相关的金融风控、公安刑侦、社会关系、人脉分析等需求分析类业务。

《金融风控、公安刑侦、社会关系、人脉分析等需求分析与数据库实现 - PostgreSQL图数据库场景应用》

八、小结

贷款这项业务已经不是银行的专利业务,越来越多的企业都开通了类似(贷款、投资)业务。

放贷本身是一件体力活,来申请贷款的人或企业鱼龙混杂。什么样的人可以获得贷款,什么样的企业值得投资,需要经过层层审查。审查需谨慎,否则就容易成为放贷公司的烂账。

通过爬虫、合作伙伴渠道可以获得个人、企业的信息、舆情信息等,通过这些信息的有效组织,可以帮助放贷人、投资人快速的做出决策,选择是否需要放贷或投资。

业务方使用阿里云的RDS PostgreSQL, HybridDB for PostgreSQL, OSS等组合产品,减轻了业务方的数据库维护、HA、容灾、扩容、缩容等负担。业务方可以专注于应用开发,提高效率。

性能方面,远远超出业务预期(如果每秒几十万笔查询还不够,你的贷款业务得多红火呀 ^_^)。

九、参考

《三体高可用PCC大赛 - facebook\微博 like场景 - 数据库设计与性能压测》

《facebook linkbench 测试PostgreSQL社交关系图谱场景性能》

《金融风控、公安刑侦、社会关系、人脉分析等需求分析与数据库实现 - PostgreSQL图数据库场景应用》

《机票业务性能优化案例 - 阿里云RDS PostgreSQL最佳实践》

《分析加速引擎黑科技 - LLVM、列存、多核并行、算子复用 大联姻 - 一起来开启PostgreSQL的百宝箱》

《TPC-H测试 - PostgreSQL 10 vs Deepgreen(Greenplum)》

《使用PostgreSQL逻辑订阅实现multi-master》

《PostgreSQL 10 流式物理、逻辑主从 最佳实践》

《打造云端流计算、在线业务、数据分析的业务数据闭环 - 阿里云RDS、HybridDB for PostgreSQL最佳实践》

《ApsaraDB的左右互搏(PgSQL+HybridDB+OSS) - 解决OLTP+OLAP混合需求》

Flag Counter

digoal’s 大量PostgreSQL文章入口