10亿级存储挑战!看一看、微信广告、微信支付、小程序都在用的存储系统到底是怎么扛住的?!

| 导语 10亿级,是微信用户的数量级。这个庞大数字的背后,是“看一看”、“微信广告”、“微信支付”、“小程序”等业务对数据库10亿级的读写需求。那么,在此场景下诞生的 FeatureKV,到底是怎样强悍的一个存储系统呢?前端

背景:两个十亿级的挑战linux

PaxosStore 是微信内普遍应用的强一致性的分布式存储系统,它普遍支撑了微信的在线应用,峰值过亿TPS,运行在数千台服务器上,在线服务场景下性能强悍。但在软件开发中没有银弹,在面对离线产出、在线只读的数据场景,PaxosStore 面临了两个新的十亿挑战:算法

10亿 / 秒 的挑战:数据库

“看一看”团队须要一个存储系统来存放CTR过程须要用到的模型,实现存储和计算分离,使得推荐模型的大小不会受限于单机内存。小程序

每次对文章的排序打分,ctrsvr 会从这个存储系统中拉取成千上万个特征,这些特征须要是相同版本的,PaxosStore 的 BatchGet 不保证相同版本。数组

业务方预估,这个存储系统须要支持10亿/秒的QPS,PaxosStore 的副本数是固定的,没法增长只读副本。缓存

这个存储系统须要有版本管理和模型管理的功能,支持历史版本回退。安全

10亿 / 小时 的挑战:性能优化

微信内部很多团队反馈,他们须要把10亿级(也就是微信用户的数量级)信息,天天按期写到 PaxosStore 中,但 PaxosStore 的写入速度没法知足要求,有时候甚至一天都写不完,写太快还会影响现网的其余业务。服务器

PaxosStore 是一个保证强一致性的存储系统,为在线业务设计,其性能也能知足在线业务的需求。但面对这种离线灌库、在线只读、不要求强一致性保证的场景,就须要很高的成本才能知足业务的需求了。

基于数据的应用愈来愈多,这类的数据存储需求也愈来愈多,咱们须要解决这个问题,把10亿级key量的数据写入时间控制在1个小时左右。

上述场景具备定时批量写、在线只读的特色,为了解决这些场景的痛点问题,咱们基于性能强大的WFS(微信自研分布式文件系统)和稳如磐石的Chubby(微信自研元数据存储),设计并实现了 FeatureKV,它是一个高性能 Key-Value 存储系统,具备如下特色:

高性能且易于扩展

优秀的读性能: 在B70机型上,全内存的表能够有千万级的QPS;在TS80A机型上,数据存放于SSD的表能够有百万级的QPS。

优秀的写性能: 在远程文件系统性能足够的状况下,能够在1小时内完成十亿个key、平均ValueSize是400Byte的数据的写入。

易于扩展: 水平扩容(读性能)和纵向扩容(容量)能够在数小时内完成,写性能扩容只是扩容一个无状态的模块(DataSvr),能够在分钟级完成。

对批量写支持友好

任务式的写接口: 支持以 WFS/HDFS 上的文件做为输入,业务方无需编写、执行灌数据工具,支持失败重试、告警。

支持增量更新/全量更新: 增量更新是在上一个版本的基础上,对一批新输入的 Key-Value 进行覆盖写,输入中没有的 key 则保持不变。而全量更新则是丢弃上一个版本的数据,灌入一批新的 Key-Value 。

支持TTL: 支持过时自动删除功能。

具备版本管理功能

事务的 BatchGet 接口: 保证一次 BatchGet 获得的数据都是同一个版本的。

支持历史版本回退: 一次更新会产生一个递增的版本,支持历史版本回退,包括增量更新生成的版本。

固然,在软件开发中没有银弹,FeatureKV 在设计上它作了取舍:

不支持在线写入数据,当数据量较小时(GB级),FeatureKV 能够作到十分钟级的更新频率。

不保证强一致性,保证最终一致性,而且在大部分时间里能够保证顺序一致性。

FeatureKV 如今在微信内部已经普遍应用,包括看一看、微信广告、微信支付、小程序等业务,接下来会阐述 FeatureKV 的设计,并具体说明如何解决上述两个十亿挑战。

整体设计

  1. 系统架构

FeatureKV 涉及的外部依赖有三个:

Chubby:用来保存系统中的元数据。FeatureKV 内不少地方是经过对 Chubby 内的元数据轮询来实现分布式协同、通讯。

USER_FS:业务侧的分布式文件系统,能够是 WFS/HDFS ,由于 FeatureKV 的写接口是任务式的,输入是一个分布式文件系统上的路径。

FKV_WFS:FeatureKV 使用的分布式文件系统,用来存放 DataSvr 产出的、能够被 KVSvr 使用的数据文件。能够保存多个历史版本,用于支持历史版本回退。

这三个外部依赖均可以和其余业务共用。FKV_WFS 和 USER_FS 能够是同一个模块。FKV_WFS 可使用 HDFS 替代。Chubby 可使用 etcd 替代。

DataSvr:

主要负责写数据,把 USER_FS 的输入,通过数据格式重整、路由分片、建索引等流程,生成 KVSvr 可用的数据文件,写到 FKV_WFS 中。

它是一个无状态的服务,写任务的状态信息保存在 Chubby 中,扩容 DataSvr,能够增长系统的写性能。

通常部署2台就好,部分场景写任务较多能够适当扩容。

KVSvr:

对外提供读服务,经过轮询 Chubby 来感知数据更新,再从 WFS 拉取数据到本地,加载数据并提供只读服务。

它是一个有状态服务,一个 KVSvr 模块会由 K 个 Sect 和 N 个 Role 组成,共 K * N 台机器。

每一个 Sect 都有全量的数据,每次 BatchGet 只须要发往某一个 Sect,增长 Sect 能够扩容读性能,而并不会增长 BatchGet 的 rpc 次数。

相同的 Role 负责的数据切片都是同样的,单机故障时 Batch 请求直接换机重试就好。

K 最少是2,用以保证系统的容灾能力,包括在变动时候的可用性。

N 不能是任意一个数字,能够看下面第二部分。

写入流程:

FeatureKV 只支持批量写入数据,每次写任务能够是增量更新/全量更新的,每次写入的数据量大小无限制。离线的批量写接口设计,咱们踩过一些坑:

一开始咱们打算封一些类/工具,打算让业务端直接用咱们的类/工具,打包Key-Value数据,直接写到 FKV_WFS 的目录上。该方案最省带宽,可是这样作让咱们后续的数据格式升级变得很麻烦,须要让全部业务方配合,因此这个方案就废弃了。

而后,咱们起了一个新模块 DataSvr,在 DataSvr 上面开了一个 tcp svr,业务侧输出 Key-Value,写入工具会把 Key-Value 数据发过来这个 tcp svr 完成打包,可是仍是有下面这些问题:

写入的速度与业务方的代码质量、机器资源有关,曾经碰到过的状况是,业务方的代码里面用 std::stringstreams 解析浮点数输入,这个函数占用了 90%+ 的 CPU(用 std::strtof 会快不少),或者业务方跑写入工具的机器,被别的进程用了 90%+ 的 CPU ,最后反馈 FeatureKV 写得很慢。

DataSvr 的平常变动或机器故障,会致使任务失败。前端工具发包的方法没法对任务进行重试,由于 Key-Value 的输入流没法重放。

最终,咱们设计了一个任务式的接口,以 USER_FS 上的路径做为输入:

业务侧把数据按照约定好的格式,放在 USER_FS 中,向 DataSvr 提交一个写任务。

DataSvr 流式读取 USER_FS 中的数据,对数据进行格式重整、路由分片、建索引,而后把数据写入 FKV_WFS 中,并更新 Chubby 中的元数据。其中写任务的分布式执行、失败重试等,也须要经过 Chubby 来同步任务状态。

KVSvr 经过轮询 Chubby 感知数据更新,把数据拉取到本地,完成加载并提供服务。

  1. 数据路由

考虑扩缩容,FeatureKV 会把一个版本的数据切分为 N 份, N 如今是 2400,经过哈希 HashFun(key) % N 来决定 key 属于那份文件。

KVSvr 加载哪些文件是由一致性哈希决定的,角色相同的 KVSvr 会加载相同一批在扩缩容的时候,数据腾挪的单位是文件。

因为这个一致性哈希只有 2400 个节点,当 2400 不能被 sect 内机器数量整除时,会出现比较明显的负载不均衡的状况。因此 FeatureKV 的 sect 内机器数得可以整除2400。还好 2400 是一个幸运数,它 30 之内的因数包括 1,2,3,4,5,6,8,10,12,15,16,20,24,25,30 ,已经能够知足大部分场景了。

上图是 N=6 时候的例子,Part_00[0-5] 表示 6 份数据文件。从 RoleNum=2 扩容成 RoleNum=3 的时候,只须要对 Part_003 和 Part_005 这两份文件进行腾挪,Part_005 从 Role_0迁出至 Role_2,Part_003 从 Role_1 迁出至 Role_2。

因为现网所用的 N=2400 ,节点数较少,为了减小每次路由的耗时,咱们枚举了 RoleNum<100 && 2400%RoleNum==0 的全部状况,打了一个一致性哈希表。

  1. 系统扩展性

FeatureKV 的 FKV_WFS 上存有当前可用版本的全部数据,因此扩容致使的文件腾挪,只须要新角色的机器从 FKV_WFS 拉取相应编号的文件,旧角色机器的丢弃相应编号的文件便可。

当 BatchSize 足够大的时候,一次 BatchGet 的 rpc 数量等价于 Role 数量,这些 rpc 都是并行的。当 Role 数量较大时,这些 rpc 出现最少一个长尾请求的几率就越高,而 BatchGet 的耗时是取决于最慢一个 rpc 的。上图展现了单次 rpc 是长尾请求的几率是 0.01% 的状况下,不一样 Role 数量状况下的 BatchGet 长尾几率,经过公式 1 - (0.999^N) 计算。

增长 Sect(读性能扩容):

每一个 Sect 都有全量的数据,增长一个 Sect 意味着增长一个只读副本,能够达到读性能扩容的效果。

因为一个 BatchGet 只须要发往一个 Sect ,RPC 数量是收敛的,不会由于底下的 KVSvr 有 200 台而发起 200 次 RPC。这种设计能够下降 BatchGet 操做的平均耗时,减小长尾请求出现的几率。

增长 Role(存储容量+读性能扩容):

假设每台机的存储能力是相等的,增长 Role 的数量即可以增长存储容量。

因为整个模块的机器都多了,因此读性能也会增长,整个模块在读吞吐量上的扩容效果等价于增长 Sect。

但当 Role 数量较大时,一次 BatchGet 涉及的机器会变多,出现长尾请求几率会增大,因此通常建议 Role 的数量不要超过30。

增长 DataSvr(写性能扩容):

DataSvr 是一个无状态服务,能够作到分钟级的扩容速度。

底下的写任务是分布式的跑,一次写会切分为多个并行的 job,增长 DataSvr 的实例数,能够增长整个模块的写性能。

数据迁移都是以文件为级别,没有复杂的迁移逻辑,不考虑灰度流程的话,能够在小时级完成,考虑灰度流程通常是一天内。

  1. 系统容灾

KVSvr 侧:

每一个 Sect 的机器是部署在同一个园区的,只须要部署 2 个 Sect 就能够容忍一个园区的机器故障。

具体案例:2019年3月23号,上海南汇园区光缆被挖断,某个 featurekv 有 1/3 的机器在上面,故障期间服务稳定。

故障期间部分 RPC 超时,致使长尾请求增长。可是换机重试以后大部分请求都成功了,最终失败出现次数很低。后续全局屏蔽了南汇园区的机器以后,长尾请求和最终失败彻底消失。

DataSvr/WFS 侧:

即使这两部分整个挂掉, FeatureKV 的 KVSvr 仍是能够提供只读服务,对于大部分 定时批量写、在线只读 的场景,这样已经足够了。

具体案例:2019年6月3号,某个分布式文件系统集群故障,不可用9小时。某个 featurekv 的 USER_FS 和 FKV_WFS 都是这个集群。故障期间业务方的输出产出流程也中止了,没有产生写任务。整个故障期间,featurekv 的读服务稳定。

十亿每秒的挑战-在线读服务的具体设计

  1. KVSvr 读性能优化

为了提升 KVSvr 的性能,咱们采起了下面一些优化手段:

高性能哈希表:针对部分数据量较少、读请求很高的数据,FeatureKV 能够用 MemTable 这一个全内存的表结构来提供服务。Memtable 底层实现是一个咱们本身实现的只读哈希表,在 16 线程并发访问的时候能够达到 2800w 的 QPS,已经超过了 rpc 框架的性能,不会成为整个系统瓶颈。

libco aio:针对部分数据量较大、读请求要求较低的数据,FeatureKV 能够用 BlkTable 或 IdxTable 这两种表结构来提供服务,这两表结构会把数据存放在 SSD 中。而 SSD 的读性能须要经过多路并发访问才能彻底发挥。在线服务不可能开太多的线程,操做系统的调度是有开销的。这里咱们利用了 libco 中对 linux aio 的封装,实现了协程级的多路并发读盘,通过压测在 value_size 是 100Byte 的状况下,TS80A 上 4 块 SSD 盘能够达到 150w+/s 的QPS。

数据包序列化:在 perf 调优的过程当中,咱们发现 batch_size 较大的状况下(ctrfeaturekv 的平均 batch_size 是 4k+),rpc 数据包的序列化时耗时会较大,因此这里咱们本身作了一层序列化/反序列化,rpc 层的参数是一段二进制 buffer。

数据压缩:不一样业务对数据压缩的需求是不同的,在存储模型的场景,value 会是一段浮点数/浮点数数组,表示一些非 0. 特征。这时候若是用 snappy 这类明文压缩算法,效果就不太好了,压缩比不高并且浪费 cpu。针对这类场景,咱们引入了半精度浮点数(由 kimmyzhang 的 sage 库提供)来作传输阶段的数据压缩,下降带宽成本。

  1. 分布式事务 BatchGet 的实现

需求背景:更新分为全量更新和增量更新两种,一次更新包括多条数据,每次更新都会让版本号递增,BatchGet 也会返回 多条数据。业务方但愿这些更新都是事务的,BatchGet 的时候若是一个更新没有所有执行完,那就返回上一个版本的数据,不能返回半新半旧的数据。

RoleNum=1 的状况:

数据没有分片,都落在同一台机器上,咱们调研后发现有这么两种作法:

MVCC: 多版本并发控制,具体实现就是 LevelDB 这样的存储引擎,保存多版本的数据,能够经过 snapshot 控制数据的生命周期,以及访问指定版本的数据。这种方案的数据结构须要同时支持读写操做,后台也得有线程经过清理过时的数据,要支持全量更新也是比较复杂。

COW: 写时复制,具体的实现就是双 Buffer 切换,具体到FeatureKV的场景,增量更新还须要把上一个版本的数据拷贝一份,再加上增量的数据。这种方案的好处是能够设计一个生成后只读的数据结构,只读的数据结构能够有更高的性能,缺点是须要双倍的空间开销。

为了保证在线服务的性能,咱们采用了 COW 的方式,设计了 第一部分 中提到了只读哈希表,来作到单机的事务 BatchGet。

RoleNum>1 的状况:

数据分布在不一样机器,而不一样机器完成数据加载的时间点不同,从分布式的角度去看,可能没有一个统一的版本。

一个直观的想法,就是保存最近N份版本,而后选出每一个 Role 都有的、最新的一份版本。

N 的取值会影响存储资源(内存、磁盘)的开销,最少是2。为了达到这个目的,咱们在 DataSvr 侧加入了这么两个限制:

单个表的更新是串行的。

写任务开始结束以前,加多一步版本对齐的逻辑,即等待全部的 kvsvr 都加载完最新的版本。

这样咱们就能够在只保留最近 2 个版本的状况下,保证分布式上拥有一个统一的版本。在 COW 的场景下,只要把另一个 Buffer 的数据延期删除(直到下次更新才删),就能够了保留最近 2 个版本了,内存开销也不会变大。

拥有全局统一的版本以后,事务 BatchGet 应该怎么实现呢?

先发一轮 rpc 询问各 role 的版本状况?这样作会让QPS翻倍,而且下一时刻那台机可能就发生数据更新了。

数据更新、版本变更实际上是很低频的,大部分时刻都是返回最新一个版本就好了,而且能够在回包的时候带上 B-Version (即另一个 Buffer 的版本),让 client 端在出现版本不一致的时候,能够选出一个全局统一的版本 SyncVersion,再对不是 SyncVersion 的数据进行重试。

在数据更新的时候,数据不一致的持续时间多是分钟级的,这种作法会带来一波波的重试请求,影响系统的稳定性。因此咱们还作了一个优化就是缓存下这个 SyncVersion ,每次 BatchGet 的时候,若是有 SyncVersion 缓存,则直接拉取 SyncVersion 这个版本的数据。

  1. 版本回退

每一个表的元数据中有一个回退版本字段,默认是0表示不处于回退状态,当这个字段非0,则表示回退至某个版本。

先考虑如何实现版本回退:

考虑简单的状况,一个表每次都是全量更新。那么每次让都是让 KVSvr 从 FKV_WFS 拉取指定版本的数据到本地,走正常的全量更新流程就行了。

而后,须要考虑增量的状况。若是一个表每次更新都是增量更新,那么回退某个版本 Vi,就须要把 V1 到 Vi 这一段都拉到 KVSvr 本地,进行更新重放,相似于数据库的 binlog,当累计了成千上万的增量版本以后,这是不可能完成的事。

咱们须要有一个异步的 worker,来把一段连续的增量,以及其前面的全量版本,合并为一个新的全量版本,相似 checkpoint 的概念,这样就能够保证一次回退不会涉及太多的增量版本。这个异步的 worker 的实如今 DataSvr 中。

更进一步,这里有一个优化就是若是回退的版本在本地双 Buffer 中,那么只是简单的切换一下双 Buffer 的指针就好,能够作到秒级回退效果。实际上不少回退操做都是回退到最后一个正常版本,极可能是上一个版本,在本地的双 Buffer 中。

处于回退状态的表禁止写入数据,防止再次写入错误的数据。

再考虑如何解除回退:

解除回退就是让某个表,以回退版本的数据继续提供服务,而且以回退版本的数据为基础执行后续的增量更新。

直接解除回退状态,现网会先更新为回退前的版本,若是还有流量的话则会读到回退前的异常数据,这里存在一个时间窗口。

数据的版本号要保证连续递增,这一点在数据更新的流程中会依赖,因此不能简单粗暴的删除最后一段数据。

为了不这个问题,咱们借用了COW的思想,先复制一遍。具体的实现就是把当前回退的版本,写出一个全量的版本,做为最新的数据版本。

这一步须要点时间,但在回退的场景下,咱们对解除回退的耗时要求并不高。只要回退够快,解除回退是安全的,就能够了。

十亿每小时的挑战-离线写流程的具体设计

  1. 背景

DataSvr 主要的工做是把数据从 USER_FS 写入 FKV_WFS,在写入过程须要作路由切分、数据格式重建等工做,是一个流式处理的过程。

FeatureKV 中目前有三种表结构,不一样的表结构在写流程中有不同的处理逻辑:

MemTable: 数据全内存,索引是无序的哈希结构,容量受限于内存,离线写逻辑简单。

IdxTable: 索引全内存,索引是有序的数组,Key量受限于内存,离线写逻辑较为简单,须要写多一份索引。

BlkTable: 块索引全内存,索引是有序的数据,记录着磁盘中一个 4KB 数据块的 begin_key 和 end_key,容量没限制,离线写流程复杂,须要对数据文件进行排序。

  1. 单机的 DataSvr

一开始,咱们只有 MemTable,数据都是全内存的。MemTable 的数据最大也就 200+GB,这个数据量并不大,单机处理能够节省分布式协同、结果合并等步骤的开销,因此咱们有了上面的架构:

一次写任务只由一个 DataSvr 执行。

Parser 每次处理一个输入文件,解析出 Key-Value 数据,计算路由并把数据投递到对应的 Que。

一个 Sender 负责处理一个 Que 的数据,底下会对应多份 FKV_FS 的文件。FKV_FS 上的一个文件只能由一个 Sender 写入。

总的设计思想是,让能够并行跑的流程都并行起来,榨干硬件资源。

具体的实现,加入了不少批量化的优化,好比对FS的IO都是带 buffer 的,队列数据的入队/出队都是 batch 的等,尽可能提升整个系统的吞吐能力。

最终,在台 24 核机器上的写入速度能够达到 100MB/s,写入 100GB 的数据只须要 20 分钟左右。

  1. 分布式的 DataSvr

再日后,FeatureKV 须要处理十亿级Key量、TB级的数据写入,所以咱们加入了 IdxTable 和 BlkTable 这两种表结构,这对于写流程的挑战有如下两点:

生成的数据须要有序,只有有序的数据才能作到范围索引的效果,让单机的key量不受内存限制。

TB 级的写速度,100MB/s 是不够用的,写入 1TB 须要接近 3 小时的时间,而且这里是不可扩展的,即使有不少不少机器,也是 3 小时,这里须要变得能够扩展。

先考虑数据排序的问题:

咱们得先把数据切片跑完,才能把一个 Part 的数据都拿出来,对数据进行排序,前面的数据切片相似于 MapReduce 的 Map,后续的排序就是 Reduce,Reduce 中存在着较大的计算资源开销,须要作成分布式的。

Map 阶段复用上述的单机 DataSvr 逻辑,数据切分后会获得一份临时的全量结果,而后实现一个分布式的 Reduce 逻辑,每一个 Reduce 的输入是一份无序的数据,输出一份有序的数据及其索引。

这种作法有一次全量写和一次全量读的额外开销。

具体的流程以下图所示,DATASVR SORTING 阶段由多台 DataSvr 参与,每一个浅蓝色的方框表示一个 DataSvr 实例。

再考虑大数据量状况下的扩展性:

参考上图,如今 DataSvr 的排序阶段其实已是分布式的了,惟一一个单点的、没法扩容的是数据切片阶段。

实现分布式的数据切片,有两种作法:

一是每一个 DataSvr 处理部分输入的 User_Part 文件,每一个 DataSvr 都会输出 2400 个切片后的文件,那么当一次分布式切片有 K 个 DataSvr 实例参与,就会生成 2400 * K 个切片后的文件,后续须要把相同编号的文件合并,或者直接做为排序阶段的输入。

二是每一个 DataSvr 负责生成部分编号的 FKV 文件,每次都读入全量的用户输入,批处理生成一批编号的 FKV 文件。

第一种作法若是是处理 MemTable 或者 IdxTable,就须要后接一个 Merging 过程,来把 TMP_i_0, TMP_i_1, TMP_i_2 ... 合并为一个 FKV_i。而处理 BlkTable 的时候,因为其后续是有一个 Sorting 的逻辑的,只须要把 Sorting 的逻辑改成接受多个文件的输入便可。故这种作法的坏处是在数据量较少的时候,MemTable 或者 IdxTable 采用分布式数据切片可能会更慢,Merging 阶段的耗时会比分布式切片减小的耗时更多;

第二种作法生成的直接就是 2400 个文件,没有后续 Merging 流程。但它会带来读放大的问题,假设数据被切分红为 T 批,就会有 T-1 次额外的全量读开销。在数据量大的状况下,批数会越多,由于排序的数据须要所有都进内存,只能切得更小;

在小数据场景,单机的数据分片已经足够了,因此咱们选用了第一种方案。

是否分布式切分,是一个可选项,在数据量较小的状况下,能够不走这条路径,回到单机 DataSvr 的处理流程。

最终,咱们获得了一个能够线性扩展的离线处理流程,面对10亿、1TB数据的数据:

在实现 BlkTable 以前,这是一个不可能完成的任务。

在实现分布式数据切片以前,这份数据须要 120min 才能完成写入。

如今,咱们只须要 71min 即可以完成这份数据的写入。

上面这一套流程,其实很像 MapReduce,是多个 Map, Reduce 过程拼接在一块儿的结果。咱们本身实现了一遍,主要是基于性能上的考虑,能够把系统优化到极致。

现网运营情况

FeatureKV 在如今已经部署了 10+ 个模块,共 270+ 台机,业务涉及看一看,搜一搜,微信广告,小程序,微信支付,数据中心用户画像,附近的生活,好物圈等各种数业务,解决了离线生成的数据应用于在线服务的痛点问题,支撑着各种数据驱动业务的发展。

最大的一个模型存储模块有210台机:

11亿特征/s: 日均峰值 BatchGet 次数是29w/s,平均 BatchSize 是 3900,模块压测时达到过 30亿特征/s。

15ms: 96.3% 的 BatchGet 请求在 15ms 内完成,99.6% 的 BatchGet 请求在 30ms 内完成。

99.999999%:99.999999% 的事务 BatchGet 执行成功。

微信广告基于 FeatureKV 实现个性化拉取+个性化广告位置,推荐策略可以及时更新。相比于旧的方案,拉取量和收入都取得了较大的增加,拉取+21.8%,收入+14.3%。

微信支付在面对面发券以及支付风控中都有用 FeatureKV,存储了多份十亿级的特征,以前一天没法更新完的数据能够在数小时内完成更新。

总结

一开始,这类定时批量写、在线只读的需求不太广泛,通常业务会用 PaxosStore 或者文件分发来解决。

但随着愈来愈多的应用/需求都与数据有关,这些数据须要按期大规模输入到在线服务当中,并须要很强的版本管理能力,好比用户画像、机器学习的模型(DNN、LR、FM)、规则字典,甚至正排/倒排索引等,所以咱们开发了 FeatureKV 来解决这类痛点问题,并取得了良好的效果。

本文首发于云加社区公众号:QcloudCommunity

相关文章
相关标签/搜索