精华内容
下载资源
问答
  • SAP-MDM主数据管理

    热门讨论 2013-04-09 16:39:03
    本书结合了SAP官方最新技术以及作者在主数据管理领域持续多年个大型项目经验,通过从原理到架构、从功能到实现,深入浅出、图文并茂地介绍了SAP MDM主数据管理解决方案。  权威——作者之中的和轶东先生和曹...
  • 体量大、种类,是我国积分行业的现状,中国人均拥有积分种类超过20种,大到三大运营商,航空公司,银行,大型商城,小到街边的便利店,超市,理发店等等,积分分布的非常零散,而且渠道相对比较封闭。 而用户在...

    体量大、种类多,是我国积分行业的现状,中国人均拥有积分种类超过20种,大到三大运营商,航空公司,银行,大型商城,小到街边的便利店,超市,理发店等等,积分分布的非常零散,而且渠道相对比较封闭。

    而用户在使用、或者查询积分时,往往因为各种手续、复杂的操作,导致积分在积分商城内的兑换率只有12%。“食之无味,弃之可惜”是用户对手上的积分,一个非常无奈的看法,有相关数据统计显示,因为积分的过于分散,且在体量少的情况下没有任何用处,兑换时各种门槛等原因,导致大部分用户,只能眼看着手里的积分过期,自己却没有任何办法,进而对积分产生抵触情绪。

    最早的积分可以追溯到1793年的美国,一位杂货铺老板跟进客人进店消费的金额,获得相应数量的铜板,累计铜板可以换取礼品,这是最早期的积分形态,也就是说积分发展到现在,已经经历了差不多200多年,而这种通过回馈忠实用户的方式,也体现出了积分功能的核心:通过客户的贡献程度,来对忠实客户进行奖励,维护客户的忠诚度。之所以我们在今天,还可以看到积分这种运营方式,最主要的原因有以下几点:

    1、激励忠实客户再消费

    一般来说,商家获取新用户的成本,往往是维护老用户成本的几倍之多,而通过积分来回馈老客户的方式,只需较低的成本就能达到激励忠实客户再消费的目的。久而久之,客户对商家的贡献越高,其等级也就越高,对商家的依赖性就越强,一般情况下是不会轻易进行更换的,最终客户再消费的几率就越高,商家所获得的利益就越多。

    2、积分可以起到一定的补充作用

    在鼓励用户特定行为方面,积分可能是最有用的工具之一。就比如很多APP都设置签到获积分这一功能,其目的就是通过签到这种形式,培养用户的行为记忆,慢慢形成习惯。所以,在产品缺乏其它比较有效的运营手段时,积分可以起到一定的补充作用,从而很好的满足运营需求,帮助商家培育用户习惯、强化用户粘性。

    3、积分成本可控

    积分的发放与兑换规则,话语权都在商家手上,商家可以根据自己的需求,来进行相应调整,这样成本也就更好控制,积分作为一个行之有效的运营手段,在合理使用的情况下,积分可以帮助商家,达成事半功倍的运营效果。

     

     

    展开全文
  • 《程序员代码面试指南:IT名企算法与数据结构题目解》对IT名企代码面试各类题目的解进行了总结,并提供了相关代码实现。针对当前程序员面试缺乏专业题目汇总这一痛点,《程序员代码面试指南:IT名企算法与数据结构...
  • 《大数据:互联网大规模数据挖掘与分布式处理》源自作者在斯坦福大学教授多年的“Web挖掘”课程材料,主要关注大数据环境下数据挖掘的实际算法。书中分析了海量数据数据挖掘常用的算法,介绍了目前Web应用的许多...
  • 《大数据:互联网大规模数据挖掘与分布式处理》源自作者在斯坦福大学教授多年的“Web挖掘”课程材料,主要关注大数据环境下数据挖掘的实际算法。书中分析了海量数据数据挖掘常用的算法,介绍了目前Web应用的许多...
  • 多年持续迭代 ( 2016 年开源至今已连续维护 4 年,累计 2000+ Commits、70+ Releases,不断更新迭代中...) 常见问题 1.如何定制业务逻辑? 在后端编写 远程函数,可以拿到 session、version、当前 JSON 对象、...
  • 前道富信息科技(浙江)有限公司技术专家,参与个金融相关的系统开发,后自主创业。2015年加入51信用卡管家担任架构师,负责风控、信审、数据支持等互金相关系统的设计与开发。从2012年开始使用PostgreSQL,拥有...

    【IT168 专稿】本文根据张泽鹏老师在2018年5月12日【第九届中国数据库技术大会】现场演讲内容整理而成。

    讲师简介:

    PostgreSQL——51风控系统背后的利器

    张泽鹏,51信用卡架构师。前道富信息科技(浙江)有限公司技术专家,参与多个金融相关的系统开发,后自主创业。2015年加入51信用卡管家担任架构师,负责风控、信审、数据支持等互金相关系统的设计与开发。从2012年开始使用PostgreSQL,拥有多年PG相关的开发和实践经验。

    摘要

    51信用卡管家作为互联网金融领域的独角兽企业,在风险控制上积累了多年经验。PostgreSQL丰富的特性给风控的分析与开发工作带来极大的便利,并支撑了51实时的风控业务。本文将介绍PostgreSQL在51风控系统中的应用,并结合4个场景介绍实践经验,以及各自方案的演进过程。

    正文:

    风控业务概述

    风控,顾名思义,就是风险控制。风控业务人员需要在诸多样本里挑出有风险的样本,并把它们排除掉。就像漫画中展示的一样:找出那个不一样的家伙!

    PostgreSQL——51风控系统背后的利器

    所以,风控工作很像在玩“大家来找茬”游戏:把左边的图看成是正样本,右边的图看成是负样本,负样本会尽可能伪装得与正样本很像。风控业务人员利用他们的火眼金睛,提炼出特征与规则,辨别正负样本。

    PostgreSQL——51风控系统背后的利器

    以此图为例,风控业务人员可能会注意到“狐狸耳朵数量”这个特征,并提出“正常狐狸有两只耳朵”的规则。未来再遇到狐狸图像,就能用这条规则来快速辨别真伪。

    类比到金融风控领域,风控业务人员也会提出类似的规则。例如:符合以下条件的申请予以通过,否则拒绝:

    男性客户:年龄在22到55岁之间;

    女性客户:年龄在18到65岁之间。

    风控系统概述

    有了风控规则,就可以线下联系申贷客户收集信息,并人工判断是否符合规则。但纯人工的方式效率低下、容易出错,随着业务规模的增长,显然需要一套自动化的风控系统来代替人工方式。如果说风控规则决定了能不能做互金这个生意,那风控系统就决定了生意能做多大!

    为实现上述风控规则,需要获得客户的“年龄”与“性别”两个特征变量;而“年龄”能由“出生年份”计算得出;“出生年份”与“性别”又能从“身份证号”中获得。这意味着,只要提供一个“身份证号”作为输入,就能依次获得“出生年份”、“性别”,进而得到“年龄”,最后得到风控规则的结果。

    PostgreSQL——51风控系统背后的利器

    举个例子,有一个身份证号:330106199011110119(此为虚拟身份证号,仅供本文示例用途);按照18位身份证号的规则,首先提取第7到10位的出生年份“1990”;接着提取倒数第二位“1”,是一个奇数,说明性别是男性;然后,与今年的年份“2018”相差,得出年龄是2018-1990=28岁;最后,确认年龄28岁在男性客户的区间范围内,即最终结果是“通过”!

    PostgreSQL——51风控系统背后的利器

    这就是风控系统的工作模式:不停地用一些变量算出另一些变量,直至获得最终的结果。日常办公软件中,电子表格(如Excel)正是一款符合该工作模式的软件:使用公式,单元格可引用另一个单元格内的数据,当被引用的单元格数据发生变化时,公式的计算结果会自动更新。

    正如前文所言,一些业务刚起步的互金公司,不值得开发一套自主的风控系统,就可以用Excel来完成风控工作。将上述规则映射到Excel中,对应下图中的5行记录。除第一行的身份证号,其他值都直接或间接由身份证号衍生而来。

    PostgreSQL——51风控系统背后的利器

    上图中最后一个特征变量的公式用到了IF、OR与AND三个函数,并且依赖了B4和B5两个单元格。Excel默认已提供了丰富的函数,但某些复杂运算逻辑——例如求熵——并未提供,但Excel支持用VBA自定义函数。

    下图中定义了一个计算阶乘的函数,无需重启就能直接在公式中使用。虽说Excel不太招DBA们待见,处于鄙视链的底端,但扩展性和易用性方面窃以为能碾压不少主流的“真正”数据库。

    PostgreSQL——51风控系统背后的利器

    从功能上来讲,51的风控系统和Excel是一样的,都提供了存储能力与计算能力。下图展示了51风控系统的组成模块:其中维度等价于Excel文件;快照等价于Excel的工作表(Sheet);而Excel里的单元格(Cell)在风控的系统中称做变量,并按照所属的业务意义细分为“清洗变量”、“特征变量”、“模型变量”、“规则变量”;变量之间也有依赖关系,任务调度模块提供了类似Excel中联动修改单元格值的功能。

    PostgreSQL——51风控系统背后的利器

    综上所述,只要提供必要的输入,风控系统就会像多米诺骨牌一样,一个接着一个,联动地运算起来!

    快照数据

    快照,故名思义,是数据在某个时间点的备份。快照功能是风控系统的基础,在任何时刻发生了变量计算,系统都会将相应的输入参数、中间变量、最终结果保存成快照。这些快照数据有三类作用:

    1. 历史证据:对业务而言,无论何时访问一笔订单相关的数据都是相同的,数据不会随时间变化而变化;对开发而言,方便线上问题的定位和排查。

    2. 缓存数据:风控数据后续还会在信审、催收等系统多次用于展示,快照数据既是证据又是缓存,避免每次查询时多次计算。

    3. 建模分析:积累的快照数据后续能用于分析与建模,供机器学习等算法使用。

    数据结构

    上述例子的5个变量,转换成JSON格式后,数据结构如下:

    {

    "id_card": "330106199011110119",

    "birth_year": 1990,

    "age": 28,

    "gender": 1,

    "is_accept": 1

    }

    如前文所述,变量会根据其业务意义分类。例如按照“输入变量”、“中间特征变量”、“输出规则变量”分成三类,数据结构就变成如下更复杂的嵌套结构:

    {

    "inputs": {

    "id_card": "330106199011110119"

    },

    "features": {

    "birth_year": 1990,

    "age": 28,

    "gender": 1

    },

    "rules": {

    "is_accept": 1

    }

    }

    在真实业务场景中,数据结构往往会更复杂、嵌套更深。例如再从身份证号中解析出省市区信息,数据结构会变成三层嵌套结构:

    {

    "inputs": {

    "id_card": "330106199011110119"

    },

    "features": {

    "birth_year": 1990,

    "age": 28,

    "gender": 1,

    "address": {

    "province": "浙江省",

    "city": "杭州市",

    "district": "西湖区"

    }

    },

    "rules": {

    "is_accept": 1

    }

    }

    存储方案一:MongoDB

    保存这类复杂的嵌套JSON数据,用MongoDB这种文档型数据库是最方便的。所以第一版的快照系统底层存储采用MongoDB——JSON进JSON出。MongoDB对开发者很友好,但业务人员大多来自传统银行,他们更熟悉SAS与SQL,MongoDB之于他们而言,和保存成JSON文件没区别,都很难开展统计与分析工作。

    存储方案二:MySQL

    为协助业务快速前进,第二版的快照系统,将底层存储方案换成了业务人员更熟悉的关系型数据库——MySQL。并制定了以下规范,用于将嵌套的JSON数据,保存到一系列二维表中:

    如果值为基础类型(数值或字符串),则代表“字段”类型

    如果值为复合类型(对象或数组),则代表“表”类型

    第一层必须为“表”类型。

    每一张表必须有一个唯一主键“id”。

    嵌套的“表”,必须有一个外键字段指向上一层表的“id”。

    例如,前文的JSON数据映射成以下表结构:

     inputs:表

     id:字段,主键

     id_card:字段

     features

     id:字段,主键

     birth_year:字段

     age:字段

     gender:字段

     address:表

     id:字段,主键

     feature_id:字段,外键,指向features.id

     province:字段

     city:字段

     district:字段

     rules:表

     is_accept:字段

    将JSON拍平成二维表之后,业务人员又能愉快地使用SQL查询并分析数据了,但却给开发带来一些负担。被MongoDB惯坏之后,工程师们希望新方案能保留MongoDB直接存取JSON的能力:只要把JSON丢进来,希望系统就能自动一层一层去保存;只要给一个ID,希望系统能自动查询相关表,并将结构组织成JSON再返回。

    为此,我们开发了一个中间件——ActiveMap——对JDBC做了一层简单的封装:它能自动获得数据库的元信息——例如表名、字段名、外键依赖等——根据这些元信息,与JSON做自动映射,以实现JSON的自动拆箱和自动装箱。

    存储方案三:PostgreSQL

    方案二上线后只几个月,业务爆发式增长,很快遇到了新问题:因为风控业务的特殊性,需要频繁地新增特征变量,即频繁地添加字段。但快照数据积累很快,几个月下来平均每张表有过亿的数据量,往这些大表里新增字段或新增索引,即使业务不停工也要折腾很久。于是,在开发快照系统的第三个版本时,再次调整了底层存储,换成PostgreSQL。PostgreSQL拥有了两个强大的特性:

    1. 创建索引时用concurrently,就能并发地创建索引,不会取得任何能阻止该表上并发插入、更新或者删除的锁。

    2. 添加新的列,如果不指定默认值,就只修改元数据,能瞬间完成。

    有了这两个特性,后续新增特征变量就不用大费周章了。

    存储方案四:PostgreSQL+JSONB

    方案三上线后运行了近一年,直到某天流量爆发,平均一分钟能收到8000多笔申请,此时的数据结构已经复杂到有5、6层嵌套结构,涉及十几张表的写入,最宽的表有超过400个字段,每笔申请会瞬间产生约20万条快照记录,即每分钟保存约16亿条记录。据DBA观察,当时TPS已经突破5万大关。虽然应用层有重试机制,能保证所有任务最终都能正常完成,但数据库已经不可用。

    经过重新评估,最终用PostgreSQL自带的JSONB类型代替多表结构。这仿佛回到方案一:用MongoDB存JSON。其实,在快照系统不断升级的这两年里,51的大数据平台也同样在进步,并搭建了内部的离线数仓,线上数据会T+1同步到离线Hive仓库,同时解析JSON数据,展开成二维表。

    业务人员不再直连线上业务库,也就不关心线上库的存储形式。改造后的系统,存储效率提升了10多倍,已经能满足目前线上的业务量。

    我们从中学到:架构师在做技术选型时,都是戴着脚镣跳舞,得因地制宜,得结合环境的约束,才能给出当下最适合的方案。在方案一就采用MongoDB属于太过激进:仅考虑线上输出风控这一个环节,MongoDB是合适的方案;但全局考虑上下游系统的协作,以及各方的学习成本,MongoDB就不见得是最佳选择了。

    维度数据

    维度是快照数据依附的主体,即这些数据属于“谁”。大多数金融业务系统基本只和一个维度的数据打交道。例如,信审系统只处理订单相关的数据,清算系统只处理标的相关的数据。但风控系统会贯穿整个金融业务生命周期,例如下单前风控系统要提供用户的授信额度和信用评级,这类数据属于用户维度;下单后订单号是唯一表示,维度变成订单维度;募资时维度又变成标的维度。

    这些系统在各自处理过程中,都会从风控系统查询一些风险相关的数据,所以风控系统更像是一个横向的切面服务,而不是垂直的服务。

    不同维度的数据需要相互隔离、不能覆盖,最简单的做法是给每个维度的快照数据创建独立的表。例如上述例子中,有inputs、features、rules三类快照数据,假设只有订单维度(orders)和用户维护(users),排列组合就产生了3*2=6张表。后续,无论是新增一个维度还是新增一个快照,都需要创建一批表,所以这种方式会引起组合爆炸!

    桥接模式

    设计模式中的桥接模式可以解决这种多对多组合的问题,它将抽象部分与它的实现部分分离,使两者能独立地变化。借鉴这个思路,将“维度”与“快照”抽象成两个独立的部分,通过继承各自独立变化。如下图所示:

    PostgreSQL——51风控系统背后的利器

    虽然桥接模式可以解决组合爆炸的问题,但它毕竟属于面向对象领域,需要将诸如“继承”等面向对象的语义转换成“join”等关系型范式的语义,才能用来解决上述关系型数据库中的问题。

    例如,互金领域的订单都会包含申贷金额和期数,但结合更具体的场景,如面向个人的产品订单,需要保存申贷个人的身份证号等,而面向商家的产品订单,则需要提供营业执照等信息。用面向对象的语言设计时,通常会先定义一个抽象的订单基类,再定义个人订单与商家订单两个子类;在关系型数据库中设计时,通常会定义一个订单表,只包含公共的字段,再定义个人订单表和商家订单表,分别保存各自的扩展字段,并都包含一个外键指向订单表的订单主键。在维护旧系统的过程中,如果你经常能看到类似XXX_EXT结尾的扩展信息表,基本都属于这种模式。但这种模式读写都很麻烦:读的时候,需join多张表,继承的层次越深,join的表越多;写的时候,需做好多表插入的事务控制。

    继承表

    看起来在关系型数据库中实现桥接模式并不容易。翻看PostgreSQL官方文档、第一章、第一节:《What is PostgreSQL?》,第一句话说:PostgreSQL是一个对象-关系型数据库管理系统!它不可思议地内置了面向对象的继承功能:

    子表继承父表的字段

    父表可查询子表数据

    通过约束排除无关表:constraint_exclusion

    与父表共享一个序列

    它完美地融合了面向对象和关系型两种范式,用inherits关键字继承父表,就像Java中用extends关键字继承父类一样简单。举个例子:有两张子表children1和children2分别继承了parents父表,并各自声明了约束。

    create table parents (id serial primary key, type int, name text);

    create table children1 (primary key (id), check (type = 1)) inherits (parents);

    create table children2 (primary key (id), check (type = 2)) inherits (parents);

    select * from parents where type = 1;

    当执行第4条type=1查询时,只会扫描parents表和children1表,并不会扫描children2表。维度数据库正是利用该特性,实现了桥接模式,几乎没给开发工程师增加工作量。

    名单数据

    名单数据通常是指黑名单和白名单,一般都是随着业务发展不断积累,在风控中属于最简单直接的拦防方法。

    方案一:资源文件

    51风控项目刚起步时,只有一份几十万条记录的身份证黑名单,保存成txt文件才几MB。所以,第一期直接把名单打包进项目中:

    1. 名单作为资源文件打包进Java项目中。

    2. 系统启动时将数据加载到内存,生成HashSet。

    3. 查询时,检查key是否在集合中即可。

    方案二:Redis

    方案一简单、粗暴、有效,但上线后其他项目也想使用这份黑名单,如果在每个项目中都拷贝一份,未来往黑名单中新增记录就变得很困难。于是升级成方案二:利用Redis集群来维护名单数据,并提供查询服务。使用依旧很简单,性能也很好。

    方案二持续了很久,直到遇到一项新需求:提供模糊查询功能。例如,名单库中有“330106199011110119”这条记录,当使用“3301061990111*****”这类带掩码key来查询时,希望返回“true”。

    这个需求用Redis的SCAN也可以实现,不过SCAN毕竟还是要扫一遍所有的KEYS;另一种方法是插入明文的时候,同时插入相应的掩码,即掩码也保存在名单库中,就能用掩码查询了。这两种方法,都需要计算明文对应的掩码,只不过前者在查询时计算,后者在插入时计算。对于名单库这种一次插入多次查询的场景,后者会更适合。

    方案三:PostgreSQL+Groovy

    为了添加时生成掩码,当时总共评估了三套方案:

    1. 增强Redis:用lua或C语言改造Redis,提供一个自定义的命令(如MASK_SET)代替SET命令,自动添加掩码key。

    2. 部分取代Redis:新开一个Java工程,提供单个添加、批量添加等接口,取代直接写Redis,但最终明文和掩码的key依旧保存在Redis中,读操作直接访问Redis。

    3. 抛弃Redis:新开一个Java工程,同时提供读写名单的接口,完全屏蔽甚至抛弃Redis。

    方案一对于应用层而言非常优雅,改动量最小,但后续添加新的掩码规则时都要去修改并重新部署自定义命令,在当时的人才储备下实施成本较高;

    方案二让应用层接入成本升高,需同时接入Redis和服务接口,还需同时考虑两者的可用性与降级策略等;综合考虑之后,最终选择方案三,实施和迁移的成本都还能接受。

    考虑到掩码规则在未来一小段时间内会频繁地增删改,为避免每次修改规则都重新发布,所以不能将规则硬编码,而是用Groovy脚本作为规则配置到数据库中,这些脚本称作生成器(Generator),它们接收一个JSON作为入参,检查参数是否拥有相关字段,如果有则返回相应的掩码,否则返回空。

    此外,每新增一个Generator时,都需要全量计算明文Key相应的掩码Key;删除明文Key时,也需要关联删除相应的掩码Key。因此,还要保存Generator与Key的映射关系。原计划新工程只是封装Redis,但关联查询并非Redis所擅长,在经过一系列性能对比之后,最终决定用PostgreSQL取代Redis,设计方案如下:

    PostgreSQL——51风控系统背后的利器

    所有明文和掩码保存在Keys表中。

    Keys的数据类型采用JSONB,因为不同名单Key的类型与字段数目都有可能不同。例如有些名单是手机号码、有些是姓名+身份证号、有些是用户ID。

    被加入名单的原因存入reasons表。

    两者通过事件(Events)相关联。

    生成器保存在Generators中。

    生成器生成的掩码Key通过Relations与Events关联。

    方案四:PostgreSQL+UDF

    方案三能满足模糊查询的需求,也在生产中运用了一段时间,但整个方案相当“凑活”,使用过程中遇到不少麻烦:

    每次新增Groovy Generator时,需全量计算所有明文Keys。但因为待计算的量比较大,无法一次性快速计算完,不得不分批计算,于是又额外需要任务管理与调度功能,导致系统愈加复杂。

    无法用PostgreSQL自带的COPY命令来批量导入Keys,因为掩码Key依赖应用层用Groovy生成,只能调用应用端的接口逐个计算。

    批量导入时会占用应用层大量资源,导致正常查询请求不能得到及时响应。

    因为数据库之上架了一层应用层,整体链路变长,性能变差。

    这些麻烦归根到底,原因是数据与计算不在同一体系内,数据不得不在持久层和应用层之间来回传递;同时,因为应用层作为统一出口,诸如批量导入数据这些原本数据库已经支持的功能,又不得不在应用层再实现一遍,还实现的更加蹩脚。是否有可能通过增强现有的持久层体系,而不是额外引入一层新的应用层?这样既能充分利用持久层的现有功能,又能避免数据传输和调度的额外工作,也避免重复造轮子。

    前文提到,Redis通过模块功能支持自定义功能,Excel通过VBA也能轻松自定义函数。PostgreSQL中,通过UDF(User Defined Function),允许用C、SQL、PLPGSQL、Python等几乎所有主流编程语言,动态添加自定义函数。例如,用SQL实现计算身份证号后5位掩码的函数:

    create function id_card_mask(jsonb) returns text as $$

    select substring($1->>'id_card', 1, 13) || '*****'

    $$ language sql immutable;

    有了计算掩码的函数,再绑定一个触发器(Trigger)——插入明文数据后自动再插入相应的掩码数据。但转念一想,掩码真正的用途是用来查询,例如:

    select * from keys where id_card_mask(context) = '3301061990111*****';

    之所以一直考虑提前计算好并保存掩码结果,是避免每次查询时都反复计算。PostgreSQL提供了另一个特性——表达式索引——既能避免重复计算,又能节约空间。索引通常都创建在真实的列上,而表达式索引允许给函数的计算结果创建索引:

    create index on keys (id_card_mask(context));

    当查询条件中出现了与表达式索引中完全一致的表达式时,PostgreSQL会直接使用索引中的计算结果,并不会执行该表达式。所以,即使函数执行非常耗时,也能高效地查询!利用UDF和表达式索引,可以完全抛弃应用层,甚至连Generators和Relations这两张表也可丢弃,整体方案得到极大简化。

    来看一下优化前后的对比:优化前,磁盘空间占用接近10G,优化后只用了2G;TPS,即单位时间生成新Key的速度,优化前在应用端用Groovy脚本计算并保存,TPS约2500,优化后突破了12000。效果是非常惊人!最重要的是,可以直接用COPY等命令批量导入名单,索引能自动生成,也无需担心有遗漏。

    PostgreSQL——51风控系统背后的利器

    任务调度

    任务调度,正如前文所述,处理任务之间的依赖关系,就像解决Excel中单元格相互引用。举个例子:有A、B、C、D四个任务

     D依赖B

     D依赖C

     C依赖A

     B依赖A

    任务调度的工作就是管理任务间的依赖关系,按照有效的顺序依次执行任务。在上例中,调度系统会首先执行A、接着同时执行B和C、最后执行D。如下图所示,任务的依赖关系是有向无环图,用拓扑排序就能得到正确的执行顺序,其思想是每次取出“出度”为0的节点,这些节点不依赖其他节点,处于可执行状态。

    PostgreSQL——51风控系统背后的利器

    方案一:多表join

    每个任务创建一张与之对应的任务队列表

    每张任务表有一个status状态字段,可取值:

    submitted:待处理

    completed:已完成

    依赖某个任务,就join相应的任务队列表

    以上述4个任务为例,需创建queue_a、queue_b、queue_c、queue_d四张任务队列表。结构如下:

    create table queue_x (

    id bigint primary key,

    status text not null default 'submitted'

    );

    假设4张表中都插入一个id为1的任务,并且状态都是submitted。根据前文的依赖关系,可以算出每个任务依赖的队列状态。比如任务A,不依赖其他任务,只要队列queue_a中有一条状态为submitted状态的任务就能马上执行;任务B和C都依赖了任务A,除了各自的队列queue_b和queue_c有一条状态为submitted的任务,还需要queue_a中有一条id相同且状态为completed的任务;任务D,则需要queue_d有状态为submitted,queue_b与queue_c状态为completed。任务调度系统会根据以上依赖关系,自动生成SQL查询语句:

    select queue_a.id from queue_a where queue_a.status = 'submitted';

    select queue_b.id from queue_b inner join queue_a on queue_b.id = queue_a.id where queue_b.status = 'submitted' and queue_a.status = 'completed';

    select queue_c.id from queue_c inner join queue_a on queue_c.id = queue_a.id where queue_c.status = 'submitted' and queue_a.status = 'completed';

    select queue_d.id from queue_d inner join queue_b on queue_d.id = queue_b.id inner join queue_c on queue_d.id = queue_c.id where queue_d.status = 'submitted' and queue_b.status = 'completed' and queue_c.status = 'completed';

    1. 第一轮:queue_a的状态变成了completed;其他队列不变。

    2. 第二轮:queue_b和queue_c的状态变成completed;queue_a和queue_d状态保持不变。

    3. 第三轮:queue_d的状态变成completed;所有队列状态都变成completed。

    PostgreSQL还提供了一个特性——条件索引——可以优化查询性能:

    create index on queue_x (id) where status = 'submitted';

    条件索引只给符合条件的记录创建索引,所以索引占用的空间就非常小。因为任务实时在调度,正常情况下处于待处理的任务并不多,所以检索速度会非常快!

    方案二:数组倒排

    方案一原理简单,在任何关系型数据库中都能实现。但随着依赖数量急剧膨胀,出现超过40张表join的场景,性能急剧下降,高峰期最长耗时700多毫秒。经过研究,对方案做出了改进,用到PostgreSQL另外两个特性——数据类型和倒排索引:

    用两个数组字段取代原来任务队列表

    submits int[]

    completes int[]

    数组字段创建GIN倒排索引

    新方案极大简化了表结构,不再需要一堆任务队列表,只需要一张queues表:

    create table queues (

    id bigint primary key,

    submits int[],

    completes int[]

    );

    不仅表结构简化,连查询语句也极大的简化:

    select id from queues where submits @> '{A}';

    select id from queues where submits @> '{B}' and completes @> '{A}';

    select id from queues where submits @> '{C}' and completes @> '{A}';

    select id from queues where submits @> '{D}' and completes @> '{B,C}';

    其中@>是包含运算符,意思是左边的数组包含了右边数组中所有的元素。

    1. 初始状态:submits的值是{A,B,C,D},completes的值是{}。

    第一轮:A从submits移到completes,submits的值变成{B,C,D},completes的值是{A}。

    2. 第二轮:B和C从submits移到completes,submits的值变成{D},completes的值是{A,B,C}。

    3. 第三轮:D从submits移到completes,submits的值变成{},completes的值是{A,B,C,D}。

    优化前,40张表join的方法,平均耗时在350ms左右,最大耗时会超过700ms;优化后,平均耗时在35ms以下,业务高峰期的最大耗时也只有45ms。下降了一个数量级!

    PostgreSQL——51风控系统背后的利器

    总结

    前文总共用到了PostgreSQL数据库的9个特性:

    1. 瞬间添加无默认值新列

    2. JSONB类型

    3. 数组类型

    4. 继承表

    5. UDF

    6. 并发创建索引

    7. 表达式索引

    8. 条件索引

    9. 倒排索引

    这9个特性分别解决了风控系统中遇到的各种问题,就像是武侠中的绝世武功——独孤九剑:遇刀破刀、遇剑破剑!PostgreSQL的特性远不止这9个,诸如并行查询、空间索引等都未涉及。

    PostgreSQL不仅仅是一个提供了SQL接口的关系型数据库,更是一个类似Hadoop、拥有存储能力和运算能力的开发平台!希望本文能抛砖引玉,掌握更多PostgreSQL的特性,为开发赋能!

    展开全文
  • VIRTUAL MULTI LOGIN(VMLogin)登浏览器开发公司有着多年业内专家指导和协作,立足于国内,服务于全球用户,致力于为用户提供最高等级的隐私安全保障,让全球更用户享受安全浏览网络服务依托自主知识产权的虚拟...

    适合亚马逊跨境电商用的浏览器排名,跨境电商用户最看重的就是浏览器的防关联效果。我以一个用户的角度,大概给大家一个相关防关联浏览器的排名。

    在这里插入图片描述

    VMlogin防关联浏览器

    VIRTUAL MULTI LOGIN(VMLogin)多登浏览器开发公司有着多年业内专家指导和协作,立足于国内,服务于全球用户,致力于为用户提供最高等级的隐私安全保障,让全球更多用户享受安全浏览网络服务依托自主知识产权的虚拟多登浏览器平台形成完善的产品及服务体系。

    VMLogin秉承“以卓越的数据技术为客户创造价值,实现客户成功”的使命,凭借产品技术的创新及坚实的服务,得到了广泛认可。

    核心功能

    一、独立分开的浏览器环境

    在VMLogin内创建一个浏览器配置文件相当于建立一个独立分开的虚拟浏览器环境。每个浏览器文件的Cookies、本地存储和其他缓存文件将被完全隔离,浏览器配置文件之间无法相互泄漏信息。

    二、浏览器指纹保护

    VMLogin以最原始的方式来处理浏览器指纹。VMLogin允许网站读取和您真实指纹不同的“面部指纹”,通过这种方法代替阻止网站读取任何指纹的旧方法。

    三、简洁的浏览器自动化

    任何具有重复性的工作可以在VMLogin通过自动化完成。您可以在VMLogin内使用Selenium webdriver。其他选择还有,使用第三方自动化构造器,比如Browser Automation Studio。

    四、自动化商务工作流程

    在VMLogin中设置业务流程方便简洁。通过分享和转移浏览器配置文件的功能,您可以轻松掌控团队成员接触浏览器配置文件的权限。您可以让第一位助手创建账户,第二位进行开发,然后轻松地将这些浏览器配置文件转发给您的客户。所有的操作可以在同一个环境中完成,避免了风险和麻烦。

    Linken Sphere林肯法球浏览器

    特点:国际老牌、防关联、但英文界面不友好、支付不方便

    林肯法球是俄罗斯人开发的一款浏览器,在防关联领域属于老牌的产品,应用的是火狐Firefox浏览器的内核,可能是因为发布的早有点不思进取了。有很多地方更新的不够及时,比如界面是英文的不够友好,很多网站不兼容连gmail都登录不了,没有自带UA指纹库,需要用户自定义,一个月100刀仅支持BTC支付。所以有点落寞了,最大的优势就是不限制创建浏览器环境!

    MU浏览器(Multilogin浏览器)

    特点:国际老牌、防关联、英文界面不友好、 创建环境限制

    Multilogin变色龙浏览器是欧洲公司开发的,上线的时间最早,养ebay账号的比较多,收费是按欧元结算的,每个月是99欧,也有创建浏览器环境的限制。虽然有中文版但是注册需要审核,不一定能通过。有谷歌chrome内核的和火狐内核两个版本。虽然功能相对比较完善但是不知道为什么我们在测试的时候经常会封号,就不建议大家尝试了。
    在这里插入图片描述

    展开全文
  • 转载 高级 Java 必须突破的 10 个知识...1、Java基础技术体系、JVM内存分配、垃圾回收、类装载机制、性能优化、反射机制、线程、网络编程、常用数据结构和相关算法。2、对面向对象的软件开发思想有清晰的认识、...

    转载自 高级 Java 必须突破的 10 个知识点!

    工作多少年了,还在传统公司写if / for 等简单的代码?那你就真的要被社会淘汰了,工作多年其实你与初级工程师又有多少区别呢?那么作为一个高级Java攻城狮需要突破哪些知识点呢?

    1、Java基础技术体系、JVM内存分配、垃圾回收、类装载机制、性能优化、反射机制、多线程、网络编程、常用数据结构和相关算法。


    2、对面向对象的软件开发思想有清晰的认识、熟悉掌握常用的设计模式。


    3、熟练掌握目前流行开源框架(spring/springmvc/ibatis),并且对其核心思想、实现原理有一定认知。


    4、熟悉Oracle、MySQL等数据库开发与设计以及缓存系统Redis或 Memcached的设计和研发。


    5、熟悉底层中间件、分布式技术(包括缓存、消息系统、热部署)、消息中间件:ActiveMQ、RabbitMQ、工作流中间件:JBPM。


    6、精通shell编程,熟练应用awk、sed、grep、strace、tcudump、gdb等常用命令。


    7、有大型分布式、高并发、高负载(大数据量)、高可用性系统设计开发经验。


    8、对配置管理和敏捷研发模式有所了解(svn,git)。


    9、熟悉常见的一些解决方案及其原理:单点登录、分布式缓存、SOA、全文检索、消息中间件,负载均衡、连接池、流计算等。


    10、能大概知道市面上主流技术的特点及业务瓶颈。


    展开全文
  • 国内外主流的三维GIS软件

    热门讨论 2011-03-14 13:38:59
     特点:NVP的项核心技术,包括高效的海量空间数据管理技术、海量三维数据网络发布技术、地形、影像数据存储压缩技术、精度地形、影像数据融合技术,处于国内外领先水平,在对于三维GIS系统最重要的海量数据支持...
  •  Bob Bryla是Oracle 9i和10g的认证专家,他在数据库设计、数据库应用程序开发、培训和Oracle数据库管理等方面拥有20多年的工作经验,他也足Dodgeville的Land'End公司的首席Internet数据库设计师和Oracle DBA. ...
  •  Bob Bryla是Oracle 9i和10g的认证专家,他在数据库设计、数据库应用程序开发、培训和Oracle数据库管理等方面拥有20多年的工作经验,他也足Dodgeville的Land'End公司的首席Internet数据库设计师和Oracle DBA. ...
  • 书中实例来源于位工程师的多年积累,具有很强的实用性。 本书是第II卷,以开发人员在项目开发中经常遇到的问题和必须掌握的技术为核心,介绍了应用Visual Basic进行程序开发的方面的知识和技巧,主要包括Visual...
  • 书中实例来源于位工程师的多年积累,具有很强的实用性。 本书是第II卷,以开发人员在项目开发中经常遇到的问题和必须掌握的技术为核心,介绍了应用Visual Basic进行程序开发的方面的知识和技巧,主要包括Visual...
  • 荣兴成绩分析系统是基于微软公司的execl表格,利用宏代码和函数,调用现代成绩分析理念,总结本人多年从事中学教务工作的经验,历经半年辛苦工作才开发的适合小学,初中,高中的成绩分析系统。 荣兴成绩分析系统...
  •  Bob Bryla是Oracle 9i和10g的认证专家,他在数据库设计、数据库应用程序开发、培训和Oracle数据库管理等方面拥有20多年的工作经验,他也足Dodgeville的Land'End公司的首席Internet数据库设计师和Oracle DBA. ...
  • 多年来,博欣公司在条码自动识别技术的研究和推广中积累了丰富的应用经验,在工业生产、库存物流等条码实施过程中自主开发了MRPII、WMS、ERP等条码应用系统。 博欣公司主要服务于福建 ,深圳、上海、的广大生产、...
  • 志达物业管理软件

    2015-06-30 14:38:50
    志达物业管理软件由长沙志达信息技术有限公司自主研发、经过众多物业管理行业客户应用实践,已形成了一套规范化、专业化的业务作业流程,为物业管理行业提供最佳的信息管理解决方案。系统集成个子模块,为企业提供...
  • 书中实例来源于位工程师的多年积累,具有很强的实用性。 本书是第II卷,本书以开发人员在项目开发中经常遇到的问题和必须掌握的技术为中心,介绍了应用C#进行程序开发各个方面的知识和技巧,主要包括鼠标与键盘...
  • 书中实例来源于位工程师的多年积累,具有很强的实用性。 本书是第II卷,本书以开发人员在项目开发中经常遇到的问题和必须掌握的技术为中心,介绍了应用C#进行程序开发各个方面的知识和技巧,主要包括鼠标与键盘...

空空如也

空空如也

1 2 3 4 5 ... 10
收藏数 198
精华内容 79
关键字:

多公司多年数据自相关