2026.3.23
点赞系统的实现
技术:redis hash/set
业务:判断文章的点赞set中有无该用户id,没有就是点赞,有就是取消点赞
问题:数据库与redis的一致性(异步写/同步锁)、大key问题(拆分set)
签到系统的实现
技术:redis bitmap
业务:每个用户按月维护的bitmap,获取连续的签到市场需从当前日期开始向前遍历直到第一个0
问题:大量bitmap也占内存(mysql持久化)、跨月统计(遇到月初继续递归上一个月)、时区问题(依赖统一的UTC时间)
使用netty作为底层的通讯架构,在此基础上封装了很多消息类型,用于实现如服务注册、心跳检测、消息订阅等功能
仿照小红书开发的社交购物平台,主要基于redis实现了各种社交功能
平台优化点
- 限流:原本是滑动窗口算法的非原子性实现,后改为令牌桶+lua脚本的原子性实现。优化考虑点:1.原方案无法保持原子性 2.滑动窗口针对请求次数限流,令牌桶可以比较tokens限流 3.令牌桶支持突发流量,滑动窗口不支持
- 缓存:原本是guava cache+opensearch作的一个多级缓存,后更新为基于guava+etcd的CDC链路,保证更新的实时性。1.无需复杂的查询条件 2.通道数量不多
@transational事务失效场景
- 内部调用
- 业务有异未抛出
- 非public修饰
- 分布式事务
- 数据库不支持事务
如何介绍项目
项目主体是springboot单体架构,利用redis做缓存和限流,resttemplate进行远程调用,kafka负责写日志和计费,etcd负责配置监听。
调用链路大致上是:请求进来先走过滤器,获取请求信息(ip、requestid、url、requestTime),然后进行ak验证,然后选通道,判断限流,调用api,前后进行一些敏感词过滤,最后写入mongo(备份)和kafka,进行持久化和计费
ak验证:设计guava和redis 的多级缓存,本地获取后会写入redis,ak先去本地找,没有就去redis,再没有就调用
通道选择:优先长文本、前缀推荐、复用,负载均衡和随机选择是兜底
通道缓存:本地etcd监听配置变动,如果mysql写入成功,这个信息会同步到etcd(文件式的存储方式),如passageway/100011为key,对应value就是json数据。通道里面存了大量数据(名称、模型、端点、限流、tpm、rpm、标签)
敏感词过滤:通过前缀树优化过滤过程,远程敏感词信息的获取,思路跟通道缓存的获取差不多
计费与日志的写入:数据备份至mongo,日志数据通过kafka持久化至mysql和opensearch中。消费积压:计算消息从产生到当前时间的差值,如果持续增大,证明消费正在积压;丢包情况:记录producer端发送数量和consumer端落盘数量,在redis还能看到消费失败的消息
实习期间做的一件比较有挑战的事
说一下我这个CDC链路的设计和实现。mentor让我重新设计一下这个多级缓存的方案,主要考虑缓存的一个时效性问题。原方案是这样的,本地的每次请求都需要获取通道信息(本地->opensearch->数据中台),获取了以后将这些通道信息同步到opensearch中。现更新为本地配置监听器,基于etcd进行配置监听,数据一更新就通知本地,进行获取,并设置定时任务进行补偿。






