"昨天发的朋友圈怎么才10个赞?"小王盯着手机屏幕嘟囔着,在当今社交网络盛行的时代,点赞和评论功能已成为每个内容平台的标配,但你知道吗?当你的手指轻轻一点"点赞"按钮时,背后可能正上演着一场高并发的技术较量,我们就来聊聊如何用Redis打造一个既简单又高效的点赞评论系统。
想象一下明星发微博的场景:一分钟内可能收到数万次点赞,如果用传统数据库直接记录每次点赞,数据库可能瞬间就被压垮了,Redis作为内存数据库,读写速度极快,特别适合这种高频写操作的场景。
Redis的主要优势:
点赞的核心是记录"谁给什么点了赞",在Redis中,我们可以用集合(Set)来存储这种关系:
# 用户123给文章1001点赞 SADD article:1001:likes 123 # 取消点赞 SREM article:1001:likes 123 # 获取文章点赞数 SCARD article:1001:likes # 检查用户是否点过赞 SISMEMBER article:1001:likes 123
这种设计下,点赞、取消点赞、查询点赞数和检查点赞状态都是O(1)时间复杂度,性能极高。
评论比点赞稍微复杂些,需要存储更多信息,我们可以使用Redis的列表(List)或有序集合(Sorted Set)来存储评论:
# 添加评论 ZADD article:1001:comments 1625000000 "{\"user_id\":123,\"content\":\"好文章!\",\"time\":1625000000}" # 获取最新10条评论 ZREVRANGE article:1001:comments 0 9 WITHSCORES # 获取评论总数 ZCARD article:1001:comments
使用有序集合可以方便地按时间排序,而且还能支持分页查询。
点赞数据:
article:{article_id}:likes
评论数据:
article:{article_id}:comments
文章点赞数缓存:
article:{article_id}:likes_count
class LikeCommentSystem: def __init__(self, redis_conn): self.redis = redis_conn def like_article(self, user_id, article_id): """用户点赞文章""" if self.redis.sadd(f"article:{article_id}:likes", user_id): self.redis.incr(f"article:{article_id}:likes_count") return True return False def unlike_article(self, user_id, article_id): """用户取消点赞""" if self.redis.srem(f"article:{article_id}:likes", user_id): self.redis.decr(f"article:{article_id}:likes_count") return True return False def get_likes_count(self, article_id): """获取文章点赞数""" return int(self.redis.get(f"article:{article_id}:likes_count") or 0) def has_liked(self, user_id, article_id): """检查用户是否点赞过""" return self.redis.sismember(f"article:{article_id}:likes", user_id) def add_comment(self, user_id, article_id, content): """添加评论""" comment_data = { "user_id": user_id, "content": content, "time": int(time.time()) } return self.redis.zadd( f"article:{article_id}:comments", {json.dumps(comment_data): comment_data["time"]} ) def get_comments(self, article_id, page=1, page_size=10): """分页获取评论""" start = (page - 1) * page_size end = start + page_size - 1 return self.redis.zrevrange( f"article:{article_id}:comments", start, end, withscores=True ) def get_comment_count(self, article_id): """获取评论总数""" return self.redis.zcard(f"article:{article_id}:comments")
点赞数缓存:虽然可以通过SCARD
直接获取集合大小,但在高并发下,单独维护一个计数器性能更好。
批量操作:使用管道(pipeline)将多个操作合并减少网络往返:
pipe = self.redis.pipeline() pipe.sadd(f"article:{article_id}:likes", user_id) pipe.incr(f"article:{article_id}:likes_count") pipe.execute()
内存优化:对于大型集合,考虑使用IntSet编码:
# Redis配置 set-max-intset-entries 512
数据过期:为不活跃的内容设置过期时间,自动清理:
self.redis.expire(f"article:{article_id}:likes", 30*24*3600) # 30天
Redis是内存数据库,虽然提供RDB和AOF两种持久化方式,但为防止极端情况下的数据丢失,可以考虑:
明星发微博可能造成某些键成为热点,解决方案:
分片:将数据分散到多个Redis实例
shard_id = article_id % 4 # 假设有4个分片 redis_conn = get_redis_connection(shard_id)
本地缓存:在应用层缓存热点内容的点赞数
当单个文章的点赞数达到百万级别时,SCARD操作可能变慢,解决方案:
使用HyperLogLog进行近似计数(如果不需要精确值)
PFADD article:1001:likes_approx 123 PFCOUNT article:1001:likes_approx
定期将大数据集合归档到磁盘数据库
基于这个基础系统,我们可以轻松扩展更多社交功能:
点赞排行榜:
# 使用有序集合维护最受欢迎文章 ZINCRBY article:likes_rank 1 article:1001
互赞关系:
# 记录用户间的互赞关系 SADD user:123:liked_by 456 # 用户456赞过123的内容
点赞通知:
# 当用户点赞时,给作者发通知 LPUSH user:{author_id}:notifications "用户{user_id}赞了你的文章{article_id}"
用Redis实现点赞评论系统就像给高速跑车配上顶级引擎,既简单又高效,我们利用Redis的Set处理点赞关系,用Sorted Set存储按时间排序的评论,再配合一些计数器和缓存技巧,就能支撑起高并发的社交互动场景。
好的系统不是一开始就追求完美,而是先跑起来再不断优化,你现在就可以用几十行代码实现这个系统的基础版本,随着业务增长再逐步加入分片、持久化、监控等高级功能。
下次当你给喜欢的帖子点赞时,不妨想想背后这套精巧的系统设计,也许你的一个小小点击,正在驱动着世界上最繁忙的一些Redis实例呢!
本文由 莱睿思 于2025-07-31发表在【云服务器提供商】,文中图片由(莱睿思)上传,本平台仅提供信息存储服务;作者观点、意见不代表本站立场,如有侵权,请联系我们删除;若有图片侵权,请您准备原始证明材料和公证书后联系我方删除!
本文链接:https://vps.7tqx.com/wenda/493259.html
发表评论