简介

权重通常是指某一因素或指标相对于某一事物的重要程度。在电商中我们可以根据用户行为进行数据埋点,进而对其进行权重配分,更专业的叫法就是 用户画像 。不同的角度有不同的叫法,但是权重主要还是为了帮助我们更好的了解使用者的使用轨迹。

模块

主要划分为下面三个模块

  • 规则
  • 聚合统计
  • 数据埋点

规则

根据数据进行权重配分,因为每个数据的配分都是不同的。比如:用户每天登录一次游戏,那么就加一分这样。然后对于分值大于某个值后可以春节发个积极奖等等。

聚合统计

根据埋点获取到的数据进行聚合,比如:将每天的数据聚合成每个月,然后再匹配当前的规则进行权重配分。

数据埋点

根据前端对接埋点接口,然后将数据落地,数据的来源基本来自埋点。具体如何设计埋点可以看看那这一篇文章。如何做好数据埋点?

例子

权重系统在之前工作当中有实施过,现在大概说一下当时的情况。

  1. 定时任务拉取各个微服务系统的埋点数据
  2. 定时任务对当天数据根据权重规则进行配分并按天将数据落地
  3. 定时任务根据业务对数据进行聚合处理

规则定义

1
2
3
4
5
6
7
8
9
10
CREATE TABLE `rule_path` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`pid` int(10) unsigned DEFAULT '0' COMMENT '父级id',
`name` varchar(36) DEFAULT '' COMMENT '名称',
`is_use` tinyint(4) DEFAULT '1' COMMENT '1.使用 2.禁用',
`created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted_at` datetime DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB CHARSET=utf8mb4 COMMENT='规则路径表';
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
CREATE TABLE `rule_leaf` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`path_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '权重路径id',
`handle_type` tinyint(4) DEFAULT '1' COMMENT '权重处理类型 1.单次 2.循环',
`point` int(10) DEFAULT '0' COMMENT '配分',
`total_point` int(10) DEFAULT '0' COMMENT '配分总和',
`condition_point` int(10) DEFAULT NULL COMMENT '条件值',
`limit_type` tinyint(4) DEFAULT '1' COMMENT '上限: 1.日 2.周 3.月 4.年',
`limit` int(10) DEFAULT '0' COMMENT '上限值',
`condition_being` varchar(36) DEFAULT NULL COMMENT '字段标识开始',
`condition_end` varchar(36) DEFAULT NULL COMMENT '字段标识结束',
`is_use` tinyint(4) DEFAULT '1' COMMENT '1.使用 2.禁用',
`special` json DEFAULT NULL COMMENT '特殊字段,根据业务进行配置',
`created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted_at` datetime DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='规则叶子节点表';

配分计算

首先因为不同的规则存在不同的计算方式,所以我们可以定义一个 Context 上下文对象,使用 rule_leaf 表的主键 id 作为键值,相关的值使用计算的类。这样子我们就能够对不同的类型使用不同的计算方式了。

1
2
3
4
5
6
7
8
9
10
11
12
class WeightContext
{
private $maps = [
1 => VersionCalculate::class,
2 => LoopCalculate::class,
];

public excute($leafId, array $elements)
{
return (new $maps[$leafId]())->exec($elements);
}
}
1
2
3
4
interface CalculateInterface
{
public function exec(array $elements);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class VersionCalculate implements CalculateInterface
{
public function exec(array $elements)
{
// do somethings
}
}

class LoopCalculate implements CalculateInterface
{
public function exec(array $elements)
{
// do somethings
}
}

因为这些配置规则计算都是非常多变的, 所以在编写配分计算的时候必须要考虑到可扩展性,最后我们使用采用 策略模式 进行编写。

数据聚合

聚合是基于当前埋点数据,将天的维度聚合为周,月,年。根据不同的业务需求,我们可以聚合不同的数据维度。

缺点

埋点数据没有统一处理,导致出错问题分散在各个服务负责人身上。

优点

配分计算部分采用 策略模式 ,使得算法可以自由切换并且扩展性良好。