Redis 实践
Timeline 时间线
Twitter 有两个 timeline,一个是已关注的人的 timeline(又叫 home timeline),一个是自己发的推的 timeline(又叫 user timeline)
现在需要处理的是 home timeline(推模式),即大 V 发推之后,需要把这些推推送到这个大 V 的粉丝 home timeline 中
使用 list
1 | fanout |
参考:
- Redis Twitter Example: An Executable Tutorial 比较完整的实现(包括用户关注这些逻辑)
- Home timeline 使用 sorted set 实现
- 系统设计面试题-实现Twitter时间线和搜索
- Twitter的Timeline是怎样服务数亿用户的? 简介
- Redis实现Timeline
Leaderboard & ranking 排行榜
使用 sorted set
1 | 添加新用户 |
参考:
- How to build a Real-Time Leaderboard app Using Redis 这里提供了很多例子
- Real-time leaderboard & ranking solutions
- 【开发经验】redis排行榜功能(日榜、周榜、月榜)
- 需要初始化这些榜单,key 可以参考:dayrank:yyyy-MM-dd, weekrank:yyyy-MM-dd, monthrank:yyyy-MM
- 可以使用
z-union-store
来根据日实时计算周、月 - 什么时候计算也有多种方案:
- 每次更新日榜的时候同时更新周、月(此时不一定要用 zunionstore)。缺:压力大
- 查询周、月的时候再实时计算。缺:压力也大
- 根据业务上的要求使用后台任务计算周、月(例如:业务要求周日再计算周榜,月尾计算月榜)
- Redis实现排行榜功能(实战) Java + Spring 实现
- redis实现排行榜(日榜,周榜,月榜) Java+Spring+RedisTempalte
- 想知道谁是你的最佳用户?基于Redis实现排行榜周期榜与最近N期榜 Redis + Lua 实现
UV & DAU & MAU 独立访客,日/月活跃用户数
UV(Unique Visitor) & DAU(Daily Active Users) & MAU(Monthly Active Users)
需要考虑用户数量、用户 ID 特性、业务是否只是需要数目而不是具体的人
sorted set 使用条件:
- unique id
- 几乎没有什么条件,只是会浪费一些空间而已
- 可以查询出都是哪些用户
bitmap 使用条件:
unique id
ID 需要自增。能映射到 bitmap 中
如果不是,可以考虑注册时间(需唯一)。假设精确到秒,注册时间减平台上线时间,一个 key 可以保存 49710 个用户((2^32)/(246060)),再用多个 key 解决其他问题
用户最多只有 40 亿(2^32 个 bit)。实际上可以使用多个 key 来突破这个限制
hyperloglog 使用条件:
- unique id
- 只在乎数目,不在乎具体是谁
- 允许有误差。HLL 本来就有误差
1 | 用户登录 |
参考:
- Tracking daily active users (DAU) with Redis
- Bitmaps vs. Sets to track Monthly Active Users in Redis 没什么含量
- 用户日活月活怎么统计 - Redis HyperLogLog 详解 有对比,有 HLL 的原理
- Redis高级类型(统计全站访问量,日活跃用户)
- Redis点赞新思路 bitmap 最后提到了 UUID 和数据超过 40 亿的处理方法
Rate Limiter 限流
非滑动窗口模式(滑动窗口需要记得每秒的访问次数),算是固定窗口模式
1 | 设置 10 s 内只允许 15 个请求(固定窗口) |
参考:
- How to build a Rate Limiter using Redis
- Redis 实现限流的三种方式
- 架构师如何讲解Redis限流——滑动窗口限流
- 我司用了 6 年的 Redis 分布式限流器,可以说是非常厉害了!
最长连续登录天数
使用 bitmap 的 bitpos 操作
1 | 登录的时候 |
月签到
使用 bitmap
1 | 用户1月6号签到 |
参考:Redis实战篇(二)基于Bitmap实现用户签到功能
公司部门架构信息
1 | 添加部门架构 |
另一种使用 list 的 存法 :
1 | 这种结构在 Redis GUI 中看起来就像是树结构 |
貌似需要考量很多东西来判断
- 后端数据据是怎么存储的
- 前端的需求是什么?是否需要查看比某个部门高级的所有部门(或者换成人,查看该人的所有领导(非直接))
- 考虑使用 Redis 拓展?ioredis-tree
数据库保存树结构的方法(前四个强推):
- 大致方法:保存 pid;保存路径;关联表保存;MPT
- Hierarchical Data in Relational Databases - drib
- MySQL :: Managing Hierarchical Data in MySQL
- Storing a Tree Structure in a Relational Database | Baeldung on Computer Science
- 数据库 - 树状结构的数据表如何设计? - SegmentFault 思否
- Hierarchical to relational database migration - Search
- MySQL:如何将树形结构存储在数据库中_数据库存储树形结构的数据_劰的劰的博客-CSDN博客
- 如何在数据库中存储一棵树 - VinoZhu - 博客园
- 树状结构存储与读取之Modified Preorder Tree - 腾讯云开发者社区-腾讯云
- 聊聊mysql的树形结构存储及查询 - 掘金
- Hierarchical Data (SQL Server) - SQL Server | Microsoft Learn
文章 tag
- 根据文章找到 tag
- 根据 tag 找文章
使用 set
1 | 新文章(同时更新该文章有多少 tag,以及某个 tag 下有多少文章) |
其他
- 面试官:Redis 的常见使用场景有哪些?
- 计算出7天都在线的用户
bitop and result <day_1> <day_2> ... <day_7>
(每个用户映射到一个 bit) - 点赞、签到、打卡 set
- 商品筛选 sdiff sinter sunion
- 计算出7天都在线的用户
- 2 万字 + 20 张图| 细说 Redis 九种数据类型和应用场景
- 删除共享锁的时候需要确定删除操作只能是上锁客户端,可以把 client-id 存到 string 中,释放前判断一下(最好 Lua 脚本原子操作)
- 共同关注 set 的 sinter 操作
- 抽奖 set 的 spop 操作(事先把候选人放到 set 中,再
spop <key> [多少个]
) - 滴滴打车(特殊数据类型)
- Redis Use Case Examples for Developers