论坛
# 首页
Caffeine 缓存库来实现帖子列表的缓存。
// 帖子列表缓存
private LoadingCache<String, List<DiscussPost>> postListCache;
// 帖子总数缓存
private LoadingCache<Integer, Integer> postRowsCache;
用法,在构造中的build指定加载器来加载缓存项。如果缓存不命中则调用加载器返回值
对比Redis
caffeine是基于本地应用中的内存的,相比没有网络IO延迟
caffeine 可以作为一级缓存,Redis作为二级缓存
# 帖子详情页
传入帖子id
帖子当前帖子信息,作者信息,点赞数量, 点赞状态,评论列表,评论中的回复列表。
查询一个帖子,查询MySQL。
查询帖子的作者,查询Redis --> MySQL。
查询该帖子的点赞数量,查询Redis。
查询当前用户是否对该帖子点赞,查询Redis。
查询这个帖子的评论,查询MySQL。
查询这个评论的用户,查询Redis --> MySQL。
查询这个评论的点赞,查询Redis。
查询当前用户是否对该评论点赞,查询Redis。
查询这个评论的回复,查询MySQL。
查询这个评论的回复的用户,查询Redis --> MySQL。
查询这个评论的回复的目标用户,查询Redis --> MySQL。
查询这个回复的点赞数量,查询Redis。
查询当前用户是否对该回复点赞,查询Redis。
查询这个帖子的回复数量,查询MySQL。
# 点赞、关注
操作Redis,没有将数据持久化存储到MySQL中。
判断是否已经对该实体点赞(1.帖子,2.评论),开启Redis事务
从该帖子的点赞集合中移除当前用户id;
获赞用户的值减一。
添加点赞信息;
获赞用户的值加一。
查询某个实体被点赞的数量,Redis
判断当前用户是否对该实体点赞,用于显示(已赞,赞)。
如果刚刚进行了点赞,那么触发点赞事件。
消费点赞事件,对于评论,点赞,关注统一消费
从事件中取出实体,写入message表,发送站内通知。
获取用户关注了谁
查询关注数,Redis;
查询关注人,Redis set。
# 定时任务
对于发布帖子,点赞帖子,评论帖子,都将该帖子id存入到Redis post:score
集合中。
创建一个简单的quartz定时器,每五分钟执行一次。
每次执行,将Redis post:score
集合中取出来,重新计算帖子的分数,同时存入到数据库中,和elasticsearch中。(这里没有事务)
与xxl-job相同,采用竞争数据库锁的方式,来保证一个任务只能有一个节点来执行。性能较差,后续也有改为分布式锁。
xxl-job支持任务分片。
# 拦截器
# WebMvcConfigurer
从cookie中取出登录凭证,查询凭证对应的用户id,Redis
查询用户,Redis ---> MySQL
将用户存入SecurityContextHolder。
# WebSecurityConfigurerAdapter
这里配置哪些路径,需要哪些权限。
如果身份认证失败,则执行commence()方法
如果权限不够,则执行handle()方法。
对于SecurityContextHolder,Spring Security中第二个过滤器会将其存入到HTTPSession中。
第二个过滤器 SecurityContextPersistenceFilter
当请求到来时,从HttpSession中获取SecurityContext并存入SecurityContextHolder中,这样在同一个请求的后续处理过程中,通过SecurityContextHolder获取数据
当一个请求处理完毕时,从SecurityContextHolder中获取SecurityContext并存入HttpSession中,方便下一个请求到来时,再从HTTPSession中拿来使用,同时擦除SecurityContextHolder中的登录信息。
# 扩展
将点赞,关注行为持久化存储到MySQL。扩展业务,我觉得可以有两种方式,一种可以用AOP,面向切面来扩展,另一种直接写新的业务逻辑,在需要的地方直接调用。考虑到点赞、关注的消息需要存储到Redis,需要保持Redis、MySQL的数据一致性,采用最终一致性的策略,将增删改事件发布RabbitMQ消息,消费者去将数据存储到MySQL。所以客户看到的点赞消息,都是从Redis中存取的。如果异步策略失败,那就是RabbitMQ如何保证消息的可靠了。
要扩展MySQL,新建点赞表(uid, entity_type, entity_id),好友表(uid, friend_id),同时计算分数的话,也要需要查询帖子的点赞数,同时将帖子,也要存到Redis中,用