本文目录导读:

在 PHP 项目中实现用户分群,核心思路是根据用户属性、行为数据、标签等,将用户动态划分到不同的群组,以便后续进行精细化运营(如推送、A/B测试、个性化推荐)。
实现用户分群通常有以下几个关键步骤和方案:
数据准备与建模
这是分群的基础,你需要决定依据哪些数据来分群。
- 基础属性:性别、年龄、注册时间、地域、设备类型等。
- 行为数据:登录频率、购买次数、浏览商品类目、点击特定功能、页面停留时长、互动行为(点赞/评论/分享)。
- 业务标签:会员等级、是否为付费用户、用户生命周期(新用户、活跃用户、沉睡用户、流失用户)、消费偏好(高客单价、低客单价)。
- 自定义属性:业务特有的字段,如“是否开通了某项服务”、“最后一次使用时间”。
数据来源:
- 关系型数据库(MySQL):存储用户基础表、订单表、行为日志表等。
- 缓存数据库(Redis):存储实时在线状态、高频访问的标签、活跃用户ID集合。
- 搜索引擎/分析型数据库(Elasticsearch/ClickHouse):存储和分析大量行为日志,支持复杂查询和聚合。
- NoSQL数据库(MongoDB):适合存储用户画像的JSON文档,字段灵活、可动态扩展。
用户分群方案选型
根据业务实时性要求和数据量大小,可以选择以下方案:
基于数据库标签字段(适合简单、静态分群)
直接在用户表(users)或用户扩展表中增加一个或多个标签字段(如 user_group、is_vip、segment_id),通过定时任务(Cron Job)或事件触发(如用户注册、购买后)来更新该字段。
- 优点:实现简单、查询快(直接索引)。
- 缺点:标签字段固定,不灵活;分群规则变更时需要修改表结构和代码。
// 示例:根据用户消费金额更新用户群组
public function updateUserSegment(int $userId) {
$totalSpent = Order::where('user_id', $userId)->sum('amount');
if ($totalSpent > 10000) {
$segment = 'high_value';
} else {
$segment = 'normal';
}
User::where('id', $userId)->update(['segment' => $segment]);
}
基于标签系统(动态、可扩展性强)
为每个用户维护一组标签(Tag),标签可以是键值对(如 is_vip: true)或类型标签(如 标签类型:消费偏好,标签值:高客单价)。
- 数据库设计:新建
user_tags表(user_id,tag_name,tag_value或tag_id),或者使用Redis Set存储每个用户的标签集合。 - 分群逻辑:通过查询拥有某些特定标签组合的用户来实现,例如查询“VIP用户且最近30天有购买”的用户群。
实现步骤:
- 定义标签体系。
- 通过监听事件(如下单成功事件)为用户打标签。
// 示例:使用Laravel事件监听给用户打标签
class UserTagManager {
// 使用 Redis Set 存储用户标签
public function addTag(string $userId, string $tag): void {
Redis::sadd("user:tags:$userId", $tag);
// 同时维护反向索引,方便按标签查询用户
Redis::sadd("tag:users:$tag", $userId);
}
// 分群查询:查找同时拥有多个标签的用户(交集)
public function getUsersByTags(array $requiredTags): array {
if (empty($requiredTags)) {
return [];
}
$keys = array_map(fn($tag) => "tag:users:$tag", $requiredTags);
return Redis::sinter($keys); // 返回用户ID数组
}
}
// 使用场景
$tagManager = new UserTagManager();
$tagManager->addTag(123, 'is_vip');
$tagManager->addTag(123, 'last_30_day_purchase');
// 查找所有VIP且在最近30天有购买的用户
$vipBuyerIds = $tagManager->getUsersByTags(['is_vip', 'last_30_day_purchase']);
基于规则引擎(灵活、适合运营人员)
运营人员可以在后台动态创建分群规则,(性别=女 AND 年龄在18-25之间) OR (最近7天登录≥3次)”,系统解析这些规则并生成SQL或使用缓存计算结果。
- 实现方式:
- 可视化规则配置:后台界面让运营人员选择字段、运算符(等于、大于、包含)、值,组合成规则。
- 规则存储:将规则配置存储为JSON格式。
- 规则解析与执行:PHP解析规则配置,转化为SQL WHERE条件或直接调用Elasticsearch查询。
// 简化的规则配置示例
$rule = [
'logic' => 'OR',
'conditions' => [
['field' => 'gender', 'op' => '=', 'value' => 'female'],
['field' => 'age_range', 'op' => 'BETWEEN', 'value' => [18, 25]],
],
];
// PHP 解析规则并生成 MySQL WHERE 语句(简化示例)
function ruleToSql(array $rule): string {
$conditions = [];
foreach ($rule['conditions'] as $cond) {
$field = $cond['field'];
$value = is_string($cond['value']) ? "'".$cond['value']."'" : $cond['value'];
$conditions[] = "{$field} {$cond['op']} {$value}";
}
$glue = $rule['logic'] === 'OR' ? ' OR ' : ' AND ';
return implode($glue, $conditions);
}
基于分析型数据库(适合海量数据、实时性要求高)
对于百万、千万级用户和大量行为数据,使用MySQL直接查询会非常慢,此时推荐使用 Elasticsearch 或 ClickHouse。
- 数据同步:将用户基础信息和行为数据实时或准实时同步到ES/CH中。
- 分群查询:利用ES的Bool Query、聚合分析或ClickHouse的SQL复杂查询能力,快速计算符合条件的人群数量或用户ID列表。
- 优点:查询速度快、支持复杂聚合计算、适合海量数据。
- 缺点:额外增加系统复杂度和维护成本。
// 使用 Elasticsearch PHP Client 查询
$params = [
'index' => 'users',
'body' => [
'query' => [
'bool' => [
'must' => [
['term' => ['gender' => 'female']],
['range' => ['age' => ['gte' => 18, 'lte' => 25]]],
],
'must_not' => [
['term' => ['is_blacklisted' => true]],
],
],
],
'size' => 0, // 只获取数量
],
];
$response = $client->count($params);
$count = $response['count'];
分群的展现与使用
- 计算群组:根据规则计算出所有符合条件的用户ID集合。
- 存储群组:将结果存储到一个群组ID-用户ID集合的映射关系里(例如Redis Set或MySQL的中间表
user_segments)。 - 更新机制:
- 离线更新:通过定时任务(如每5分钟、每小时)全量或增量更新计算。
- 实时更新:用户发生行为时,实时增删用户群组关系,计算量大时,可配合消息队列(RabbitMQ/Kafka)异步处理。
- 运营使用:在推送通知、弹窗、首页配置等场景,直接读取
user_segments表中该用户所属的群组,展示对应的内容。
总结与最佳实践
| 方案 | 适用场景 | 数据量级 | 实时性 | 实现复杂度 | 维护成本 |
|---|---|---|---|---|---|
| 数据库字段标签 | 分群规则固定、数量少 | 小 | 高 | 低 | 低 |
| 标签系统(Redis/MongoDB) | 分群规则动态、标签灵活 | 中 | 高 | 中 | 中 |
| 规则引擎 | 运营人员频繁自定义规则 | 中 | 中 | 高 | 高 |
| Elasticsearch/ClickHouse | 海量数据、复杂行为分析分群 | 大 | 高 | 高 | 高 |
推荐做法(快速上手):
- 小项目(MVP):直接用MySQL加几个标签字段即可。
- 中型项目(1万-10万用户):采用Redis标签系统 + 定时任务或事件驱动打标签,支持动态查询。
- 大型项目(10万+用户):将用户画像数据同步到Elasticsearch,提供API接口给前端调用,运营后台使用规则引擎配置。
关键注意点:
- 数据一致性:用户标签和核心业务数据需要保持同步,避免出现用户属于“高价值群组”但实际已流失的情况。
- 性能:避免在用户请求的主流程中执行复杂分群计算,用异步队列或离线处理。
- 可扩展性:设计标签和规则时预留扩展接口,支持未来增加新的字段和规则类型。