<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
提到點贊,大家一想到的是不是就是朋友圈的點贊呀?其實點贊對我們來說並不陌生,我們經常會在手機軟體或者網頁中看到它,今天就讓我們來了解一下它的實現吧。我們常見的設計思路大概分為兩種:一種自然是用 MySQL 等資料庫直接落地儲存, 另外一種就是將點讚的資料儲存到 Redis 等快取裡,在一定時間後刷回 MySQL 等資料庫。
首先我們來說一下兩種方法各自的優缺點:我們以 MySQL 和 Redis 為例。
1、直接寫入資料庫:
優點:這種方法實現簡單,只需完成資料庫的增刪改查就行;
缺點:資料庫讀寫壓力大,如果遇到熱門文章在短時間內被大量點讚的情況,直接運算元據庫會給資料庫帶來巨大壓力,影響效率。
2、使用 Redis 快取:
優點:效能高,讀寫速度快,緩解資料庫讀寫的壓力;
缺點:開發複雜,不能保證資料安全性即 redis 掛掉的時候會丟失資料, 同時不及時同步 redis 中的資料, 可能會在 redis 記憶體置換的時候被淘汰掉。不過對於點贊資料我們不需要那麼精確,丟失一點資料問題不大。
接下來就從以下三個方面對點贊功能做詳細的介紹
•Redis 快取設計
•資料庫設計
•開啟定時任務持久化儲存到資料庫
Redis 的整合我們在上一篇文章中已經介紹過了,此處就不再贅述了。我們瞭解到,我們在做點讚的時候需要記錄以下幾類資料:一類是某使用者被其他使用者點讚的詳細記錄,一類是。考慮到查詢與存取方便快捷,我這邊採用 Hash 結構進行儲存,儲存結構如下:
(1)某使用者被其他使用者點讚的詳細記錄: MAP_USER_LIKED
為鍵值, 被點贊使用者id::點贊使用者id 為 filed, 1或者0 為 value
(2)某使用者被點讚的數量統計: MAP_USER_LIKED_COUNT
為鍵值, 被點贊使用者id 為 filed, count
為 value
/** * 將使用者被其他使用者點讚的資料存到redis */ @Override public void saveLiked2Redis(String likedUserId, String likedPostId) { String key = RedisKeyUtils.getLikedKey(likedUserId, likedPostId); redisTemplate.opsForHash().put(RedisKeyUtils.MAP_KEY_USER_LIKED,key, LikedStatusEnum.LIKE.getCode()); } //取消點贊 @Override public void unlikeFromRedis(String likedUserId, String likedPostId) { String key = RedisKeyUtils.getLikedKey(likedUserId, likedPostId); redisTemplate.opsForHash().put(RedisKeyUtils.MAP_KEY_USER_LIKED,key,LikedStatusEnum.UNLIKE.getCode()); } /** * 將被點贊使用者的數量+1 */ @Override public void incrementLikedCount(String likedUserId) { redisTemplate.opsForHash().increment(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT,likedUserId,1); } //-1 @Override public void decrementLikedCount(String likedUserId) { redisTemplate.opsForHash().increment(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, likedUserId, -1); } /** * 獲取Redis中的使用者點贊詳情記錄 */ @Override public List<UserLikeDetail> getLikedDataFromRedis() { Cursor<Map.Entry<Object,Object>> scan = redisTemplate.opsForHash().scan(RedisKeyUtils.MAP_KEY_USER_LIKED, ScanOptions.NONE); List<UserLikeDetail> list = new ArrayList<>(); while (scan.hasNext()){ Map.Entry<Object, Object> entry = scan.next(); String key = (String) entry.getKey(); String[] split = key.split("::"); String likedUserId = split[0]; String likedPostId = split[1]; Integer value = (Integer) entry.getValue(); //組裝成 UserLike 物件 UserLikeDetail userLikeDetail = new UserLikeDetail(likedUserId, likedPostId, value); list.add(userLikeDetail); //存到 list 後從 Redis 中刪除 redisTemplate.opsForHash().delete(RedisKeyUtils.MAP_KEY_USER_LIKED, key); } return list; } /** * 獲取Redis中的使用者被點贊數量 */ @Override public List<UserLikCountDTO> getLikedCountFromRedis() { Cursor<Map.Entry<Object,Object>> cursor = redisTemplate.opsForHash().scan(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, ScanOptions.NONE); List<UserLikCountDTO> list = new ArrayList<>(); while(cursor.hasNext()){ Map.Entry<Object, Object> map = cursor.next(); String key = (String) map.getKey(); Integer value = (Integer) map.getValue(); UserLikCountDTO userLikCountDTO = new UserLikCountDTO(key,value); list.add(userLikCountDTO); //存到 list 後從 Redis 中刪除 redisTemplate.opsForHash().delete(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT,key); } return list; }
這裡我們可以和直接將點贊資料存到資料庫一樣,設計兩張表:
(1)使用者被其他使用者點讚的詳細記錄:user_like_detail
DROP TABLE IF EXISTS `user_like_detail`; CREATE TABLE `user_like_detail` ( `id` int(11) NOT NULL AUTO_INCREMENT, `liked_user_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '被點讚的使用者id', `liked_post_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '點讚的使用者id', `status` tinyint(1) NULL DEFAULT 1 COMMENT '點贊狀態,0取消,1點贊', `create_time` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT '建立時間', `update_time` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改時間', PRIMARY KEY (`id`) USING BTREE, INDEX `liked_user_id`(`liked_user_id`) USING BTREE, INDEX `liked_post_id`(`liked_post_id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '使用者點贊表' ROW_FORMAT = Dynamic; SET FOREIGN_KEY_CHECKS = 1;
(2)使用者被點讚的數量統計:user_like_count
DROP TABLE IF EXISTS `user_like_count`; CREATE TABLE `user_like_count` ( `id` int(11) NOT NULL AUTO_INCREMENT, `like_num` int(11) NULL DEFAULT 0, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; SET FOREIGN_KEY_CHECKS = 1;
我們使用 Quartz 來實現定時任務,將 Redis 中的資料儲存到資料庫中,為了演示效果,我們可以設定一分鐘或者兩分鐘儲存一遍資料,這個視具體業務而定。在同步資料的過程中,我們首先要將 Redis 中的資料在資料庫中進行查重,捨棄重複資料,這樣我們的資料才會更加準確。
//同步redis的使用者點贊資料到資料庫 @Override @Transactional public void transLikedFromRedis2DB() { List<UserLikeDetail> list = redisService.getLikedDataFromRedis(); list.stream().forEach(item->{ //查重 UserLikeDetail userLikeDetail = userLikeDetailMapper.selectOne(new LambdaQueryWrapper<UserLikeDetail>() .eq(UserLikeDetail::getLikedUserId, item.getLikedUserId()) .eq(UserLikeDetail::getLikedPostId, item.getLikedPostId())); if (userLikeDetail == null){ userLikeDetail = new UserLikeDetail(); BeanUtils.copyProperties(item, userLikeDetail); //沒有記錄,直接存入 userLikeDetail.setCreateTime(LocalDateTime.now()); userLikeDetailMapper.insert(userLikeDetail); }else{ //有記錄,需要更新 userLikeDetail.setStatus(item.getStatus()); userLikeDetail.setUpdateTime(LocalDateTime.now()); userLikeDetailMapper.updateById(item); } }); } @Override @Transactional public void transLikedCountFromRedis2DB() { List<UserLikCountDTO> list = redisService.getLikedCountFromRedis(); list.stream().forEach(item->{ UserLikeCount user = userLikeCountMapper.selectById(item.getKey()); //點贊數量屬於無關緊要的操作,出錯無需拋異常 if (user != null){ Integer likeNum = user.getLikeNum() + item.getValue(); user.setLikeNum(likeNum); //更新點贊數量 userLikeCountMapper.updateById(user); } }); }
至此我們就實現了基於 Redis 的點贊功能,我們還需要注意一點:查詢使用者點贊情況時,需要同時查詢資料庫+快取中的資料。
以上就是利用Redis實現點贊功能的範例程式碼的詳細內容,更多關於Redis點贊功能的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45