欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

利用Redis實現(xiàn)點贊功能的示例代碼

 更新時間:2022年06月28日 15:25:30   作者:阿Q說代碼  
點贊對我們來說并不陌生,我們經(jīng)常會在手機(jī)軟件或者網(wǎng)頁中看到它。今天就讓我們來了解一下如何用Redis實現(xiàn)這一功能吧,感興趣的可以嘗試一下

提到點贊,大家一想到的是不是就是朋友圈的點贊呀?其實點贊對我們來說并不陌生,我們經(jīng)常會在手機(jī)軟件或者網(wǎng)頁中看到它,今天就讓我們來了解一下它的實現(xiàn)吧。我們常見的設(shè)計思路大概分為兩種:一種自然是用 MySQL 等數(shù)據(jù)庫直接落地存儲, 另外一種就是將點贊的數(shù)據(jù)保存到 Redis 等緩存里,在一定時間后刷回 MySQL 等數(shù)據(jù)庫。

MySQL 和 Redis優(yōu)缺點

首先我們來說一下兩種方法各自的優(yōu)缺點:我們以 MySQL 和 Redis 為例。

1、直接寫入數(shù)據(jù)庫:

優(yōu)點:這種方法實現(xiàn)簡單,只需完成數(shù)據(jù)庫的增刪改查就行;

缺點:數(shù)據(jù)庫讀寫壓力大,如果遇到熱門文章在短時間內(nèi)被大量點贊的情況,直接操作數(shù)據(jù)庫會給數(shù)據(jù)庫帶來巨大壓力,影響效率。

2、使用 Redis 緩存:

優(yōu)點:性能高,讀寫速度快,緩解數(shù)據(jù)庫讀寫的壓力;

缺點:開發(fā)復(fù)雜,不能保證數(shù)據(jù)安全性即 redis 掛掉的時候會丟失數(shù)據(jù), 同時不及時同步 redis 中的數(shù)據(jù), 可能會在 redis 內(nèi)存置換的時候被淘汰掉。不過對于點贊數(shù)據(jù)我們不需要那么精確,丟失一點數(shù)據(jù)問題不大。

接下來就從以下三個方面對點贊功能做詳細(xì)的介紹

•Redis 緩存設(shè)計

•數(shù)據(jù)庫設(shè)計

•開啟定時任務(wù)持久化存儲到數(shù)據(jù)庫

1、Redis 緩存設(shè)計及實現(xiàn)

Redis 的整合我們在上一篇文章中已經(jīng)介紹過了,此處就不再贅述了。我們了解到,我們在做點贊的時候需要記錄以下幾類數(shù)據(jù):一類是某用戶被其他用戶點贊的詳細(xì)記錄,一類是??紤]到查詢與存取方便快捷,我這邊采用 Hash 結(jié)構(gòu)進(jìn)行存儲,存儲結(jié)構(gòu)如下:

(1)某用戶被其他用戶點贊的詳細(xì)記錄: MAP_USER_LIKED 為鍵值, 被點贊用戶id::點贊用戶id 為 filed, 1或者0 為 value

(2)某用戶被點贊的數(shù)量統(tǒng)計: MAP_USER_LIKED_COUNT 為鍵值, 被點贊用戶id 為 filed, count 為 value

部分代碼如下

/**
* 將用戶被其他用戶點贊的數(shù)據(jù)存到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());
}

/**
* 將被點贊用戶的數(shù)量+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中的用戶被點贊數(shù)量
*/
@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;
}

Redis 存儲結(jié)構(gòu)如圖

2、數(shù)據(jù)庫設(shè)計

這里我們可以和直接將點贊數(shù)據(jù)存到數(shù)據(jù)庫一樣,設(shè)計兩張表:

(1)用戶被其他用戶點贊的詳細(xì)記錄: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 '點贊狀態(tài),0取消,1點贊',
  `create_time` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT '創(chuàng)建時間',
  `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)用戶被點贊的數(shù)量統(tǒng)計: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;

3、開啟定時任務(wù)持久化存儲到數(shù)據(jù)庫

我們使用 Quartz 來實現(xiàn)定時任務(wù),將 Redis 中的數(shù)據(jù)存儲到數(shù)據(jù)庫中,為了演示效果,我們可以設(shè)置一分鐘或者兩分鐘存儲一遍數(shù)據(jù),這個視具體業(yè)務(wù)而定。在同步數(shù)據(jù)的過程中,我們首先要將 Redis 中的數(shù)據(jù)在數(shù)據(jù)庫中進(jìn)行查重,舍棄重復(fù)數(shù)據(jù),這樣我們的數(shù)據(jù)才會更加準(zhǔn)確。

部分代碼如下

//同步redis的用戶點贊數(shù)據(jù)到數(shù)據(jù)庫
@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());
        //點贊數(shù)量屬于無關(guān)緊要的操作,出錯無需拋異常
        if (user != null){
            Integer likeNum = user.getLikeNum() + item.getValue();
            user.setLikeNum(likeNum);
            //更新點贊數(shù)量
            userLikeCountMapper.updateById(user);
        }
    });
}

至此我們就實現(xiàn)了基于 Redis 的點贊功能,我們還需要注意一點:查詢用戶點贊情況時,需要同時查詢數(shù)據(jù)庫+緩存中的數(shù)據(jù)。

以上就是利用Redis實現(xiàn)點贊功能的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于Redis點贊功能的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • redis字符串類型_動力節(jié)點Java學(xué)院整理

    redis字符串類型_動力節(jié)點Java學(xué)院整理

    這篇文章主要為大家詳細(xì)介紹了redis字符串類型的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • Redis如何實現(xiàn)分布式鎖

    Redis如何實現(xiàn)分布式鎖

    相信大家對鎖已經(jīng)不陌生了,本文主要介紹了Redis如何實現(xiàn)分布式鎖,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • 64位Windows下安裝Redis教程

    64位Windows下安裝Redis教程

    這篇文章主要介紹了64位Windows下安裝Redis教程,本文使用Microsoft Open Tech group 在 GitHub上開發(fā)的一個Win64版本的Redis,需要的朋友可以參考下
    2014-09-09
  • 淺談redis采用不同內(nèi)存分配器tcmalloc和jemalloc

    淺談redis采用不同內(nèi)存分配器tcmalloc和jemalloc

    下面小編就為大家?guī)硪黄獪\談redis采用不同內(nèi)存分配器tcmalloc和jemalloc。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-12-12
  • Redis高級數(shù)據(jù)類型Hyperloglog、Bitmap的使用

    Redis高級數(shù)據(jù)類型Hyperloglog、Bitmap的使用

    很多小伙伴在面試中都會被問道 Redis的常用數(shù)據(jù)結(jié)構(gòu)有哪些?可能很大一部分回答都是 string、hash、list、set、zset,但其實還有Hyperloglog和Bitmap,本文就來介紹一下
    2021-05-05
  • Redis緩存-序列化對象存儲亂碼問題的解決

    Redis緩存-序列化對象存儲亂碼問題的解決

    這篇文章主要介紹了Redis緩存-序列化對象存儲亂碼問題的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Redis遍歷海量數(shù)據(jù)集的幾種實現(xiàn)方法

    Redis遍歷海量數(shù)據(jù)集的幾種實現(xiàn)方法

    Redis作為一個高性能的鍵值存儲數(shù)據(jù)庫,廣泛應(yīng)用于各種場景,包括緩存、消息隊列、排行榜,本文主要介紹了Redis遍歷海量數(shù)據(jù)集的幾種實現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-02-02
  • CentOS下Redis數(shù)據(jù)庫的基本安裝與配置教程

    CentOS下Redis數(shù)據(jù)庫的基本安裝與配置教程

    這篇文章主要介紹了CentOS下Redis數(shù)據(jù)庫的基本安裝與配置教程,Redis一般被用作基于內(nèi)存的緩存式數(shù)據(jù)存儲,要的朋友可以參考下
    2015-12-12
  • Windows下Redis的安裝使用圖解

    Windows下Redis的安裝使用圖解

    Redis是一個key-value存儲系統(tǒng)。Redis的出現(xiàn),很大程度補(bǔ)償了memcached這類key/value存儲的不足,在部分場合可以對關(guān)系數(shù)據(jù)庫起到很好的補(bǔ)充作用。這篇文章小編為大家分享了在Windows下進(jìn)行安裝和使用Redis的技巧。
    2015-09-09
  • Redis的Cluster集群搭建的實現(xiàn)步驟

    Redis的Cluster集群搭建的實現(xiàn)步驟

    本文檔只對Redis的Cluster集群做簡單的介紹,并沒有對分布式系統(tǒng)的所涉及到的概念做深入的探討。感興趣的小伙伴們可以參考一下
    2021-07-07

最新評論