FeatureDB概述

特征数据库(下文简称FeatureDB)是阿里云PAI平台下特征平台(PAI-FeatureStore)提供的数据库服务,可以作为FeatureStore的在线数据源,提供在线特征存储功能,并为搜索推荐广告等服务提供高性能的读写优化。本文为您介绍什么是FeatureDB,以及FeatureDB的功能与优势。

什么是FeatureDB

FeatureDBFeatureStore提供的高性能分布式存储数据库,支持KV、KKV格式的数据,并支持以结构化的方式将数组存储为Array,将KV存储为Map类型。通过Array、Map类型存储数据,可以为后续的读写、推理服务提供更高的性能。FeatureDB已经全面支持离线特征和实时特征的生产、更新与消费链路,同时也支持用户行为序列特征。

产品特性

FeatureDB针对FeatureStore特征读取特性实现了如下功能和优化:

  • 支持读写KV、KKV类型特征。

  • 支持读写MaxCompute复杂类型特征(Array、Map)。

  • 支持全量拉取FeatureView下的所有特征数据。

  • 支持毫秒级轮询更新实时特征数据。

  • 支持秒级TTL,自动清理过期数据。

  • 按量计费,根据实际读写数据量进行计费。

FeatureDB可以对FeatureView的数据进行分片存储,通过调整分片数来满足不同场景的读写性能需求,并且支持副本,以保障数据的稳定与安全。其中,分片数量可以根据特征存储的数据量进行调整:

  • 5分片(默认):适用于千万级以下的数据量。

  • 10分片:适用于千万级以上、亿级以下的数据量。

  • 20分片:适用于亿级以上的数据量。

image

产品优势

  • 高性价比

    对于特征存储规模较小的客户,使用FeatureDB可以降低使用成本。

  • 满足高频更新需求

    当使用实时统计特征时,需每隔几秒及时更新实时特征到多个EasyRec Processor(模型推理服务)实例的存储中,这对高频更新有较高的要求,FeatureDB可以满足这一需求。

  • 支持复杂类型特征

    在搜索推广业务中,ArrayMap类型的特征、用户行为长序列特征及其SideInfo被广泛使用。如果复杂类型特征以字符串形式存储,在应用时需要进行序列化为Map类型,会降低性能。

    FeatureDB支持存储复杂类型数据,并支持同步MaxCompute2.0复杂类型数据到FeatureDB,进行高性能读取操作。

  • 支持弹性扩容

    对于规模较大的客户,能够根据特征视图灵活增加分片数量,提高读写性能。

  • 解决监控盲点

    当集成第三方数据源时,整个数据链路的监控变得困难,特别是在实时特征方面。FeatureDB能够监控每个视图粒度的读写QPS、RT、数据更新延时和存储用量等关键性能指标。

产品功能

配置FeatureDB数据源

具体操作,请参见配置数据源

写入特征

对于离线特征,可以使用FeatureStore Python SDK通过DataWorks每天例行运行调度任务,将MaxCompute里的数据同步到FeatureDB中。

对于实时特征,目前可通过以下两种方式同步数据。

  • 方式一:直接通过Java SDK写入特征数据。

           // 配置 regionId, 阿里云账号, FeatureStore project
           Configuration configuration = new Configuration("cn-beijing",
                    Constants.accessId, Constants.accessKey,"fs_demo_featuredb" );
    
            // 配置 FeatureDB 用户名,密码
            configuration.setUsername(Constants.username);
            configuration.setPassword(Constants.password);
    
            // 如果使用公网链接 FeatureStore, 参考上面的域名信息
            // 如果使用 VPC 环境,不需要设置
            //configuration.setDomain(Constants.host);
    
            ApiClient client = new ApiClient(configuration);
    
            // 如果使用公网链接 设置 usePublicAddress = true, vpc 环境不需要设置
            // FeatureStoreClient featureStoreClient = new FeatureStoreClient(client, Constants.usePublicAddress);
            FeatureStoreClient featureStoreClient = new FeatureStoreClient(client );
    
            Project project = featureStoreClient.getProject("fs_demo_featuredb");
            if (null == project) {
                throw  new RuntimeException("project not found");
            }
    
            FeatureView featureView = project.getFeatureView("user_test_2");
            if (null == featureView) {
                throw  new RuntimeException("featureview not found");
            }
    
            List<Map<String, Object>> writeData = new ArrayList<>();
            // 模拟构造数据写入 
            for (int i = 0; i < 10; i++) {
                Map<String, Object> data = new HashMap<>();
                data.put("user_id", i);
                data.put("string_field", String.format("test_%d", i));
                data.put("int32_field", i);
                data.put("int64_field", Long.valueOf(i));
                data.put("float_field", Float.valueOf(i));
                data.put("double_field", Double.valueOf(i));
                data.put("boolean_field", i % 2 == 0);
                writeData.add(data);
            }
    
            for (int i = 0; i < 100;i++) {
                featureView.writeFeatures(writeData);
            }
    
            // 这里只需要调用一次,如果全部数据写完,确保全部写入完成,调用此接口后,无法再调用 writeFeatures 
            featureView.writeFlush();
    
  • 方式二:使用实时计算Flink生产实时特征,通过配置Flink Connector写入。具体操作,请参见设置Flink Connector

对于实时特征写入,默认我们会进行整行数据更新。如果写入数据只包含了部分字段,对于未写入的字段我们会将其设置为空。如果想要只更新写入字段的数据,并将其合并到原有数据上,您可以进行如下设置:

  • 通过Java SDK写入:指定 InsertMode 写入模式,设置为 InsertMode.PartialFieldWrite。

    for (int i = 0; i < 100;i++) {
        featureView.writeFeatures(writeData, InsertMode.PartialFieldWrite);
    }
  • 通过配置Flink Connector写入:设置参数 insert_mode 值为 partial_field_write。

读取特征

您可以使用FeatureStore SDK(Go/Java)或EasyRec Processor读取特征。

FeatureStore SDK(Go/Java )支持离线/实时特征的KV点查。通过指定特征的JoinID(主键)值与特征名称,即可在毫秒内完成键值对(KV)查询,获取目标特征数据。FeatureStore SDK(Go/Java)也支持行为序列特征的KKV查询。通过指定UserID(用户ID)值,即可查询到拼装好的序列特征结果。

EasyRec Processor已集成FeatureStore Cpp SDK,支持将FeatureDB的特征数据全量拉入内存,并支持毫秒级轮询更新实时特征数据到内存,从而实现更高性能的读取。

监控指标

如果使用FeatureDB作为在线数据源,创建特征视图后,单击目标视图右侧的数据监控,可查看该视图的读写QPSRT等指标。image

image

实时特征链路

image

FeatureStore提供的存储服务主要包括三部分:Feature Service(接入层)、消息队列(DataHub)和FeatureDB。

在实时特征中,用户可以通过FeatureStore Java SDKFlink Connector调用Feature Service服务,将特征数据写入FeatureDB。通过Feature Service写入的数据,也会同步到用户的MaxCompute表中,可以用于实时特征的样本导出,进一步的模型训练。

对于存储在FeatureDB中的特征数据, 用户可以通过FeatureStoreJava/Go SDK读取,也可以通过 EasyRec Processor全量拉取特征存入本地缓存中,以实现更高性能的读取。对于实时特征,可以毫秒级获取最新特征信息。

实时特征数据生命周期设置

在创建实时特征视图时,可以通过特征生命周期来设置FeatureDB表的数据生命周期。当一行数据的生存时间到达生命周期后,它会在几秒内被自动清理。

image

数据的生存时间目前支持两种设置方式:

  • 方式一:不设置事件时间字段。这种情况下,会根据数据的写入时间开始计算生存时间,到达生命周期后,自动清理数据。

  • 方式二:勾选了某个特征字段作为事件时间字段,单位是毫秒。假设 event_time 为事件时间字段的值, time_now 为现在的时间,time_ttl = time_now - ttl 为应该开始过期的 event_time 的值,这种情况下对于写入的特征数据的具体处理方式如下:

    • 如果使用 PartialFieldWrite 模式进行部分字段更新写入,则会根据数据实际写入时间计算生存时间。

    • event_time > time_now + 15min:数据不写入。(这里防止不同系统之间时间戳有差异,放宽15分钟)

    • time_ttl < event_time <= time_now + 15min:数据正常写入,根据 event_time 开始计算生存时间,到达生命周期后,自动清理这行数据。

    • 0 < event_time < time_ttl:数据写入后会被自动清理。这里需要注意的是,event_time的单位是毫秒。如果您的事件时间字段的值是秒,那么会落入这种情况,导致数据写入不成功。

    • event_time <= 0:根据数据实际写入时间计算生存时间。

    • 值非法(无法转换成整型):数据不写入。

    • 注册了事件时间字段但是没有传入事件时间字段的值:数据正常写入,根据数据实际写入时间计算生存时间。

    • 不注册事件时间字段:数据正常写入,根据数据实际写入时间计算生存时间。

    • 另外,在FeatureDB中,我们会将 event_time 的值作为这行数据的ts,意味着如果需要更新一个 key 对应的数据,需要事件时间字段的值比之前的值大,这行数据才会更新。如果新的 event_time <= 原来 event_time 的值,则不会更新这个key对应的数据。

性能测试

以下是使用FeatureStore SDK读取FeatureDB特征的性能压测示例,特征表数据选取的推荐情景中user侧数据,总数据行数是8671932,数据仅供参考。

在线数据源

特征字段数量(列数)

读取keys数量(行数)

平均耗时

TP99

FeatureDB

260

1

3.25毫秒

4.34毫秒

FeatureDB

260

10

3.52毫秒

4.62毫秒

FeatureDB

260

50

4.51毫秒

6.05毫秒

FeatureDB

260

200

8.23毫秒

10.52毫秒

FeatureDB

260

500

12.96毫秒

16.55毫秒

FeatureDB

260

1000

17.61毫秒

21.26毫秒

相关文档

特征平台(FeatureStore)计费说明