1.为什么我要写这篇博客?
我在刷小红书的时候偶然看到一篇自己喜欢的文章,我毫不吝啬的给他点了个赞,在红心在屏幕上亮起来的时候,我的注意力被红星从文章中拉了出来。
此时我在想点赞这种如此高并发的功能应该怎么实现呢?
我带着我的疑问来到CSDN中试图找到一篇可以清楚讲解实现原理的文章。
可是我找到的各种结果都不尽人意,不是直接在数据库直接操作点赞数量自增的,就是点赞接口使用了Redis的同时又使用数据库自增且不带锁的操作。
很显然上面那种操作根本不能使用到线上业务中,性能低的同时还会出现线程安全问题。
所以我看完这些文章后心血来潮,自己思考了一种既能够实现点赞功能,又能够保证性能和并发安全的方案。 也许方案中可能会出现不合理的,或者有问题的地方,我希望大家也能在评论中不吝赐教。
2.点赞业务分析
2.1 高并发:
往往这种业务并发量非常大,比如说如果一个百万甚至千万的博主在中午12点午高峰发布了一篇非常有含金量的文章,那么这个文章的点赞并发量肯定不会很低。
2.2 数据库同步要求低:
点赞数量我们只需要前端看着数量对得上就行,一般对到后台数据库中的数据和缓存中的数据一般只要求最终一致性,不要求时时一致。
2.3 同一用户点赞的唯一性:
我们同一个用户一般点赞某一个文章只能点击一次,再点击一次就是取消点赞。
3. 技术选型和解决方案
根据以上3种特点,我们可以进行技术选型
1 点赞使用Redis 的Set类型 Key 使用(“Blog:likes+文章ID”),Value 使用 (点赞用户ID),而外使用一个String类型用户记录文章总点赞数,数据库与缓存同步机制使用MQ消息队列进行异步同步。
2点赞使用Redis 的Set类型 Key 使用(“Blog:likes+文章ID”),Value 使用 (点赞用户ID),而外使用一个String类型用户记录文章总点赞数,数据库与缓存同步机制使用定时任务进行同步缓存
在这里我只推荐这两种方案,至于为什么使用异步而不使用同步,主要是这个业务要保证数据库并发性能首先就不能使用锁来保证线程安全问题和同步操作进行数据库的短时间多次修改,也不需要在数据库中记录中间状态,只需要保证最终一致性,有的人就要提问 既然不需要中间状态为什么你还要使用MQ异步同步,所以方案1不是我最推荐的,相比之下我最最推荐方案2, 方案2的优势就是,不论中间你对点赞数据进行了多少次修改,在最后我对数据库的修改只有一次,所有的并发点赞的IO操作都在Redis中。