【黑马点评】Redis 高级数据结构在社交与统计场景的降维打击
引言
在完成了高并发秒杀(Seckill)模块的硬核攻坚后,我们对 Redis 的理解从简单的 String/Hash 缓存跃升到了分布式锁与原子性控制。然而,Redis 的强大不仅仅在于“快”,更在于其丰富的数据结构能优雅地解决复杂的业务场景。
本文将复盘《黑马点评》后半部分的核心功能:好友关注、Feed 流推送、基于 LBS 的附近商户、海量用户签到与 UV 统计。这部分内容展示了 Redis 在社交网络(Social Network)和大数据统计(Big Data Statistics)场景下的应用。
一、 社交关系的基石:好友关注 (Set)
1. 业务场景
用户关注博主、取消关注;查看两个人的“共同关注”。
2. 传统 MySQL 痛点
如果在 MySQL 中做“共同关注”,需要复杂的 JOIN 查询:
SQL
SELECT * FROM tb_follow f1 JOIN tb_follow f2 ON f1.user_id = f2.user_id ...
随着数据量增加,这种全表扫描或索引交叉的效率极低。
3. Redis 解决方案:Set 集合
利用 Redis Set 的无序、唯一、支持集合运算的特性。
- 存储结构: key =
follows:userId, value ={targetId1, targetId2...} - 关注/取关:
SADD/SREM。
核心亮点(共同关注): 直接使用 SINTER (Intersection) 命令。
- Bash
SINTER follows:UserA follows:UserB
Redis 在内存中进行集合交集运算,速度比数据库 Join 快几个数量级。
二、 信息流设计:达人探店 Feed 流 (Sorted Set)
1. 业务场景
博主发布新笔记,粉丝的收件箱(Inbox)里能刷到这些笔记,并按时间倒序排列。
2. 架构选型:Push 还是 Pull?
这是面试中的高频考点。
- 拉模式 (Pull/读扩散): 博主发帖只存自己库,粉丝上线时去拉取所有关注博主的帖子并排序。优点是省空间,缺点是粉丝上线加载慢(高延迟)。
- 推模式 (Push/写扩散): 博主发帖后,直接推送到所有粉丝的收件箱。优点是粉丝读取极快,缺点是博主如果是大 V(千万粉丝),写扩散压力巨大。
本项目策略: 采用推模式 (Push)。因为是点评类应用,大 V 相对较少,为了保证用户体验,牺牲一部分写入性能换取读取性能。
3. Redis 解决方案:ZSet (Sorted Set)
我们需要一个既能存 ID,又能排序的结构。
- Key:
feed:userId(每个用户都有一个收件箱) - Value:
blogId(笔记 ID) - Score:
timestamp(发布时间戳)
当博主发帖时,遍历其粉丝列表,执行:
Bash
ZADD feed:粉丝ID 时间戳 笔记ID
用户读取时,使用 ZREVRANGEBYSCORE 实现滚动分页(解决传统分页在动态列表中数据重复或丢失的问题)。
三、 LBS 地理位置:附近商户 (GEO)
1. 业务场景
用户打开 App,查询“我周围 3km 内的火锅店”,并按距离排序。
2. 底层原理:GeoHash
Redis 的 GEO 模块并非只有 API,其底层是 ZSet。
- 原理: 将二维的经纬度映射为一维的 Base32 字符串(GeoHash)。将地图划分为无数个网格,距离越近,GeoHash 字符串的前缀匹配度越高。
- 存储:
Member是商户 ID,Score是经纬度转换后的 52 位整数。
3. 核心优势
如果用 MySQL BETWEEN 经纬度查询,难以利用索引。Redis GEOSEARCH (或 GEORADIUS) 利用 ZSet 的跳表结构,能极其高效地搜索指定范围内的元素。
四、 大数据统计的魔法:签到与 UV
1. 场景 A:用户签到 (BitMap)
- 需求: 记录用户一年的签到情况,并统计连续签到天数。
- 痛点: 如果用数据库,一人一年 365 条记录,1000 万用户就是 36.5 亿行数据,极其浪费。
- Redis 方案:BitMap (位图)。
-
- 将一个月看作一个二进制串。第 1 天签到就把第 0 位置为 1。
- 空间占用: 1 个月 30 天 = 30 bit ≈ 4 byte。1000 万用户一个月仅需 40MB 内存。
- 统计:
BITCOUNT统计总天数;BITFIELD获取一段二进制并通过位运算(与运算、右移)计算连续签到。
2. 场景 B:UV 统计 (HyperLogLog)
- 需求: 统计网站的独立访客(UV),需要去重。
- 痛点: 使用
Set存储 IP 或 UserID 确实能去重,但如果 UV 达到千万级,内存占用几百 MB 甚至 G 级。 - Redis 方案:HyperLogLog (HLL)。
-
- 原理: 概率统计算法(伯努利试验)。通过 Hash 值末尾 0 的数量来估算基数。
- 优势: 无论统计多少数据,每个 Key 固定占用 12KB 内存。
- 代价: 约 0.81% 的误差(对于 UV 统计完全可接受)。
结语:从 CRUD 到架构思维
《黑马点评》的后半部分是对 Redis 丰富数据结构的一次深度阅兵。
- Set 解决了社交关系的交叉查询;
- ZSet 完美契合了 Feed 流的时序排序;
- GeoHash 将复杂的二维空间搜索降维成一维查找;
- BitMap & HLL 则展示了在海量数据下,如何用极致的空间换取性能。
作为后端工程师,选择合适的数据结构往往比写出复杂的算法更重要。这即是黑马点评后半部分部分真正的价值所在。
更多推荐




所有评论(0)