ホームページ  >  記事  >  データベース  >  Redisを使用してlike機能を実装する方法

Redisを使用してlike機能を実装する方法

WBOY
WBOY転載
2023-05-27 22:37:042929ブラウズ

MySQL と Redis の長所と短所

まず、2 つの方法の長所と短所について説明します。MySQL と Redis を例に挙げてみましょう。

1. データベースに直接書き込む:

利点: この方法は実装が簡単で、データベースの追加、削除、変更、クエリを完了するだけで済みます。

短所: データベースは読み取りと書き込みに大きなプレッシャーを受けます。人気のある記事が短期間に多数の「いいね!」を受け取った場合、データベースを直接操作するとデータベースに大きなプレッシャーがかかり、効率に影響します。

2. Redis キャッシュを使用する:

利点: 高いパフォーマンス、高速な読み取りおよび書き込み速度、データベースの読み取りおよび書き込みの負荷を軽減します;

欠点: 複雑な開発、データセキュリティは保証できません 問題は、redis がハングするとデータが失われることですが、同時に、redis 内のデータが同期されていない場合、redis のメモリを交換するとデータが失われる可能性があります。ただし、同様のデータについてはそれほど正確である必要はなく、多少のデータが失われることは大きな問題ではありません。

次に、同様の機能を次の 3 つの側面から詳しく紹介します。

•Redis キャッシュ設計

•データベース設計

•スケジュールされたタスクのデータベースへの永続ストレージを有効にする

1. Redis キャッシュの設計と実装

Redis を統合する方法を前の記事で紹介しましたが、ここでは再度説明を繰り返すことはありません。いいね操作を行う際には、ユーザーが他のユーザーにいいねされた詳細な記録や、いいね操作の記録を記録する必要があることを理解しています。クエリとアクセスを容易にするために、ストレージにハッシュ構造を使用しました。ストレージ構造は次のとおりです:

(1) ユーザーが他のユーザーにいいねされた詳細な記録: MAP_USER_LIKEDはキー値です。いいねされたユーザー ID:: いいねされたユーザー ID がファイルされます。値は 1 または 0 です。

(2) ユーザーのいいね数の統計: MAP_USER_LIKED_COUNT がキーです。 value であり、ユーザー ID がファイルされるのと同様に、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;
}

Redis ストレージ構造は次のとおりです

Redisを使用してlike機能を実装する方法

Redisを使用してlike機能を実装する方法

2. データベース設計

ここでは、同様のデータをデータベースに直接保存するのと同じように 2 つのテーブルを設計できます。 ##(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 &#39;被点赞的用户id&#39;,
  `liked_post_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT &#39;点赞的用户id&#39;,
  `status` tinyint(1) NULL DEFAULT 1 COMMENT &#39;点赞状态,0取消,1点赞&#39;,
  `create_time` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT &#39;创建时间&#39;,
  `update_time` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) ON UPDATE CURRENT_TIMESTAMP(0) COMMENT &#39;修改时间&#39;,
  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 = &#39;用户点赞表&#39; 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;

3. スケジュールされたタスクの永続ストレージを有効にするデータベースへ

Quartz を使用してスケジュールされたタスクを実装し、Redis のデータをデータベースに保存します。効果を実証するために、状況に応じて 1 分または 2 分に 1 回データが保存されるように設定できます。特定のビジネス。データを同期するプロセスでは、データの正確性を高めるために、最初にデータベース内の 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を使用してlike機能を実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。