0%

本文来自12月份对于风控的数据质量建设的一些思考和规划。由于业务战略的变化调整,不再继续建设,也无法通过实践来验证。不过,一些大数据指标方面的质量保障建设体系思考,我觉得还是有价值的,算是抛砖引玉了。

一、背景

在风控整体架构体系中,主要涉及平台能力和特征数据。平台能力,主要关注,规则引擎、处置审核等,风控策略运营都是基于这些平台能力来对所有风险事件进行决策、拦截、处罚、事后追偿等,是风控对外的能力提现。而对于特征数据,则是需要给能力平台的各个关键节点提供数据支撑,如果数据质量出现问题,则同样会影响整个风控最终结果的质量。

对于平台能力的质量测试,和业务测试无差别,因此,其有着丰富的理论经验和实践工具支撑。但是,和能力平台测试不同,关于数据指标的测试,首先存在实践经验的不丰富,之前的测试主要重点在于业务流程测试,对于大数据的测试理论和实践比较缺失;其次,大数据理论本身发展也非常快,同时大数据体系也比较新,每个公司、每个业务对于大数据的建设都存在多少的不一致,进而影响外部分享的数据质量测试方法在风控数据内部的落地;再次,大数据的指标测试由于数据大,可能涉及的依赖数据表较多,并且大多数表都来自各个业务方,需要从上到下去构造数据测试,成本非常大,得不偿失;最后,也是最重要的,风控特征中心是业务中的大数据,其对于大数据的指标生产和使用场景的特殊性,决定了数据质量建设的复杂性。

随着,风控业务的不断发展,对数据指标的需求也不断增多,指标的重要性也不断凸显。在长期对数据指标生产的测试迭代,运行过程中的问题发现和解决,的进程中,会有各种各样基于各个点的思考、梳理和经验产出,但是,还是缺少一些体系化的方法论总结,使得,始终无法总览数据质量治理全局。

因此,本文期望可以对于数据质量的测试和建设,进行体系化的去思考梳理,能够产出一个包含全链路的数据质量治理方法论。

阅读全文 »

上文, MySQL InnoDB 查询部分核心设计和原理主要从数据查询部分简单介绍MySQL InnoDB引擎的设计和优化。另外,关于数据库同样非常核心的部分,就是关于数据写入的设计和实现。
本文,将从数据变更写入角度,来看看MySQL InnoDB引擎的设计。

一、前言

和redis内存数据库不同,MySQL是典型的关系型数据管理系统,一个数据的写入完成,需要保证持久化到硬盘上方可。

对于一些需要写入数据到磁盘文件的应用程序而已,其需要考虑各个方面的安全问题:

  1. 如果在执行写指令的时候,数据库程序出现故障时,如何处理,保证数据正确性;
  2. 多个客户端同时执行操作某个数据,导致冲突的时候,如何保证数据正确性;
  3. 数据正在写入的时候,如果有查询该数据的请求过来,如何保证查询数据的正确性;
  4. 此外,客户端本身在多并发情况下,数据查询后处理完再写入时,如何保证数据的最终正确性;
  5. 等等。

此外,还需要保证数据处理的高性能。我们知道简单的随机写磁盘文件,首先性能上就会非常糟糕,这对于提供最核心的数据读写的基础设施而言,是非常致命的问题。

因此,我们需要好好研究MySQL InnoDB 存储引擎的设计方案。

阅读全文 »

之前有介绍过redis相关知识:redis的三高架构设计实现分析,不过redis主要是内存数据库,所以redis的优化方向主要是内存数据结构,对于磁盘持久化部分而言,不管redis 采用RDB 还是 AOF方式,对于磁盘的写,都是以顺序写的方式,基本上不存在数据更新的随机写操作,因此很多写磁盘文件的常用设计方案都不会涉及。

因此,为了想了解文件操作的一些优化思路,顺便对我们日常开发中经常使用的数据库更深入一点的了解,本文将对基于InnoDB引擎的MySQL数据库做一个稍微深一点的介绍。

MySQL InnoDB 介绍主要分为两部分:

  1. 数据查询部分,主要是索引相关介绍;
  2. MySQL InnoDB 关于 ACID部分的实现设计。

本文主要介绍 MySQL InnoDB关于数据查询部分的设计。本文主要的脉络,主要是:

  1. 首先介绍一个查询请求,从客户端到 MySQL Server 端的处理,以及被存储引擎的处理主流程;
  2. 然后在从InnoDB存储引擎的层面,探讨支持查询所采取的数据结构和处理流程;
  3. 接着,看MySQL Server 端对查询请求做的一些优化,来加快查询效率。

在开始深入了解MySQL查询设计之前,先整体了解下MySQL架构,以及常用的InnoDB存储引擎架构。

阅读全文 »

一般,互联网系统软件设计上,会有三高的概念,即 高并发,高性能,高可用。对于高并发,主要是指,系统可以在大流量请求场景下,支撑业务正常响应,应用系统不出现宕机。

业务应对高并发场景的常用手段,总结为三板斧:缓存,降级,和限流。在缓存方案集中,一般分为本地缓存,和 分布式缓存。而,针对分布式缓存,业务应用最多的技术组件,就是redis。因此,本文就来介绍redis如何以优秀的架构设计从众多开源缓存产品中脱颖而出,成为目前互联网公司缓存方案的技术组件的首选。

首先,作为支持高并发解决方案的三板斧之一的缓存,其底层支持的组件必须本身能支持高并发请求,否则依赖的缓存组件都无法响应请求了,那应用系统肯定会无法支持高并发了。

其次,缓存的价值,就是可以减少请求的处理时间,提供高性能的数据处理服务。对缓存组件的要求,就是需要用合适的资源来支持高并发请求下的快速响应。如果应用程序依赖的缓存,处理每一次请求的耗时都比较长,那么显然也没办法帮助应用程序来支持更高的并发请求了。

最后,任何一个在线互联网软件系统本身,其必须要保证高可用性。如果不断出现各种问题,并且故障出现后恢复时间长,最终导致整体SLA很低,也会影响业务系统的SLA,显然是不可以的。

因此,本文将从这三个方面来介绍 redis 是如何设计的。

阅读全文 »

一、背景

由于nsq消息队列,使用push模式进行消息分发。众所周知,push模式消费消息带来的一个难点,就是消费速率的控制。和pull模式通过consumer端自己主动拉消息来按需消费不同,push模式需要broker端根据对应consumer的消息处理能力来决定控制消息推送速率。如果控制的不当,就会导致consumer机器出现消息阻塞,最终导致业务系统出现非预期故障。

nsq本身提供RDY机制来控制推送速率,consumer客户端有自己的策略(默认策略见后面章节分析)来更新RDY值,然后定时任务,每隔1s将最新的RDY值告诉broker端,此时broker端按照新的RDY值来推送消息。

生产环境遇到的一个case,业务流程如下:

线上case流程

出现的问题,不是由于consumer客户端本身的处理能力,而是由于外部服务进行了限流,导致超过指定阈值之后,会直接返回错误,这样consumer端就会有大量的消息处理失败,从而出现非预期失败报警。

但是,我们的预期,是希望消息可以按照我们期望的速率进行消费,因此,抛开nsq自身的RDY机制,需要主动控制推送速率,也就是我们需要对消息施加主动限流。

在对nsq 消息消费进行限流之前,先对nsq consumer client端代码进行分析。

阅读全文 »

当前团队内部在每个需求开发完成,进入测试之前,会组织会议进行Code Review,主要是针对代码一行一行讲解,但是最终的效果并不是很好,尤其是很多时候对于具体技术方案都不清楚的情况下,直接讲解代码,非常低效。

此外,按照开发的思路对代码一行行讲,对于开展 CR 的价值并不大,参与评审同学只能针对格式,代码规范等进行 review,对于更顶层的代码模式设计和实现技术思想,基本上都没有体现出来,也因此无法发现一些隐层的实现细节上的漏洞。

最后,会议上的code review,时间有限,从这么多次的体验下来,没办法把所有问题反馈完整,并且后期的改造也没有完整版的 review 评论参考,无法形成一个闭环。

因此,本文就对Code Review 进行一些思考,以及通过对外部其他同行的落地实践经验进行调研梳理后,期待形成一个团队内部可推行的Code Review方案。

一、Code Review 价值和目标

首先,我们需要明确和对齐Code Review价值和目标,如果这个得不到认可,那么就不需要在团队内部推行Code Review了。例如,有些团队认为,在创新业务快速发展,不断试错的情况下,CR并不是有价值的,让业务活下来才是重中之重,代码的随意和设计的扩展性差,无所谓;等到业务稳定了再进行重构和重视代码质量。那么,在内部推行Code Review 价值就不大了,至于这些团队的想法,无可厚非,不要过于纠结对不对,其实并不重要。

接下来,从自己的角度来说说Code Review价值,同时,也是自己对新CR模式落地后能达到的期望目标:

  • 发现问题,提升代码质量。
  • 交流技术,提升团队氛围。
  • 维护约定,提升规范意识。
  • 共享业务,提升团队业务感。
阅读全文 »

零、前言

java8 推出来的时候,新上了一个反射类Parameter,可以通过这个类拿到方法的具体参数名称。但是,这个功能默认是关闭的,在使用javac 编译的时候,使用-parameters参数,才能在getName()的时候返回具体参数的名称,而不是类似arg0…之类的。很多java框架都使用了该类的新特性,让组件使用起来更便利。但是,如果我们不了解这些,没有配置对应开关参数,或者不小心关闭了开关,可能会影响到框架正常使用,从而导致奇奇怪怪的未遇到过的问题。

这篇文章,主要是在一次重构过程中,对于原始代码的调整,导致mybatis框架使用时候的异常case分析,而产出的。

阅读全文 »

一、事务型消息实现背景

如果要在交易等场景中使用消息,则一致性是非常关键的需求。也就是不能出现业务操作成功消息未发出或者消息发出了但是业务并没有成功的情况。举例来说,支付服务使用消息通知出票服务,那么不能出现支付成功,但是消息没有发出,这会引起用户投诉;但是也不能出现支付未成功,但是消息发出最后出票了,这会导致公司损失。总结一下就是发消息和业务需要有事务保证。

提到一致性,大家肯定就想到事务,而一提到事务,肯定就想到关系型数据库,那么我们是不是可以借助关系型DB里久经考验的事务来实现这个一致性呢。我们以MySQL为例,对于MySQL中同一个实例里面的db,如果共享相同的Connection的话是可以在同一个事务里的。

以上介绍来自:
https://github.com/qunarcorp/qmq/blob/master/docs/cn/transaction.md

阅读全文 »

按照一贯风格,首先看单元测试这个词组的定义,然后根据定义,来看怎样写好单元测试,他的通用规范是什么用的。

一、单元测试定义

百度百科官方定义:

单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如C语言中单元指一个函数,Java里单元指一个类,图形化的软件中可以指一个窗口或一个菜单等。总的来说,单元就是人为规定的最小的被测功能模块。单元测试是在软件开发过程中要进行的最低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。

维基百科官方定义:

在计算机编程中,单元测试(英语:Unit Testing)又称为模块测试,是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作。程序单元是应用的最小可测试部件。在过程化编程中,一个单元就是单个程序、函数、过程等;对于面向对象编程,最小单元就是方法,包括基类(超类)、抽象类、或者派生类(子类)中的方法。

每个理想的测试案例独立于其它案例;为测试时隔离模块,经常使用stubs、mock[1]或fake等测试马甲程序。单元测试通常由软件开发人员编写,用于确保他们所写的代码符合软件需求和遵循开发目标。它的实施方式可以是非常手动的(透过纸笔),或者是做成构建自动化的一部分。

从定义,可以很清楚知道,单元测试是针对方法写代码进行自动化测试,并且,我们在做单元测试的时候,针对的是所有单元的对外接⼝,对外⾏为(即public),⽽不是关注于⼀些内部的实现或者内部逻辑。此外,从维基定义中介绍,一个理想的测试case,是针对单个方法做测试,其依赖的其他外部方法和模块,都应该做隔离的,一般方法是使用mock。

阅读全文 »