用户画像数据推荐用Redis的Hash存基础信息(如user:123:profile),再用Sorted Set按权重维护兴趣标签(如user:123:interests),支持实时写入、范围查询与条件交集,避免静态快照和JSON冗余存储。

用户画像数据怎么存才方便实时查询
直接用关系型数据库查用户标签组合,响应延迟高、并发扛不住。推荐用 Redis 的 Hash 存基础画像(如 user:123:profile),再用 Sorted Set 按兴趣权重维护标签热度(如 user:123:interests,score 为点击/停留加权值)。避免把所有标签塞进一个 JSON 字段——后续没法做范围查询或条件交集。
常见错误是把画像当静态快照:用户刚搜完“咖啡机”,画像却要等凌晨 ETL 才更新。微服务里必须支持实时写入,比如监听 UserSearchEvent 消息后,立刻用 zincrby 更新对应标签 score。
- 新注册用户用默认标签兜底(如
zadd user:456:interests 1.0 "general") - 敏感标签(如年龄、地域)单独存
Hash,不进Sorted Set,避免被误用于非合规场景 - 定期用
zremrangebyrank清理低分旧标签(保留 top 20)
推送规则引擎怎么避开硬编码
硬写 if-else 判断“女性+25-35岁+美妆兴趣”就发口红广告,等于把业务逻辑焊死在代码里。应该把规则抽成 YAML 配置,由独立服务加载并编译成内存规则树。
示例配置片段:
rule_id: "cosmetic_v2"<br>conditions:<br> - field: "gender"<br> op: "eq"<br> value: "female"<br> - field: "age_range"<br> op: "in"<br> value: ["25-35"]<br> - field: "top_interest"<br> op: "contains"<br> value: ["skincare", "makeup"]<br>action:<br> template_id: "tmpl_notify_003"<br> priority: 8
立即学习“go语言免费学习笔记(深入)”;
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 字段名必须和 Redis 中的
Hashkey 严格一致(如age_range而非age) -
op: "contains"对应的是zrevrangebyscore查出的前 N 个标签,不是全量匹配 - 规则变更后需触发热重载,避免重启服务——用 fsnotify 监听文件变化即可
怎么让推送不重复也不漏发
用户可能同时命中多条规则,但同一消息 24 小时内只该推一次;也可能因服务抖动漏掉某次事件。核心是引入幂等 + 补偿机制。
每条推送生成唯一 dispatch_id = md5(userid + rule_id + timestamp_day),写入 Redis 的 Set(过期设为 25 小时)。投递前先 sismember 判重。漏发靠定时任务扫描未处理的 UserActionEvent 消息表(MySQL),按时间窗口补偿。
- 不要用本地内存缓存去判重——多实例下失效
- 补偿任务必须带
FOR UPDATE锁住待处理记录,否则并发时会重复补偿 - 用户退订开关存在
Hash里(user:789:settings),每次投递前必须hget检查push_enabled字段
性能瓶颈通常卡在哪几个地方
压测时 QPS 上不去,90% 是卡在 Redis 连接池打满或规则匹配耗 CPU。别急着加机器,先看这三处:
- Redis 连接池大小设为
min(100, CPU核数 × 4),太大反而引发 TIME_WAIT - 规则匹配不用正则,改用预编译的
switch分支(Go 的map[string]func()比反射快 3 倍) - 用户画像查询用 pipeline:一次
hmget拿 profile,再zrevrange取 top interests,别拆成两次 round-trip
最易被忽略的是模板渲染——如果用 text/template 在每次推送时解析字符串,CPU 占用飙升。正确做法是启动时预编译所有 template_id 对应的模板到内存 map 里,运行时只做 Execute。

















