Rumah  >  Artikel  >  pangkalan data  >  Cara menggunakan Redis untuk melaksanakan fungsi serupa

Cara menggunakan Redis untuk melaksanakan fungsi serupa

WBOY
WBOYke hadapan
2023-05-27 22:37:042818semak imbas

Kebaikan dan Kelemahan MySQL dan Redis

Pertama sekali, mari kita bincangkan tentang kelebihan dan kekurangan kedua-dua kaedah: Mari kita ambil MySQL dan Redis sebagai contoh.

1. Tulis terus ke pangkalan data:

Kebaikan: Kaedah ini mudah dilaksanakan, dan hanya perlu melengkapkan penambahan, pemadaman, pengubahsuaian dan semakan pangkalan data

Kelemahan: Pangkalan data berada di bawah tekanan yang hebat untuk membaca dan menulis, jika artikel popular menerima jumlah suka yang besar dalam tempoh yang singkat, mengendalikan pangkalan data secara langsung akan memberi tekanan yang besar pada pangkalan data dan menjejaskan kecekapan.

2. Gunakan cache Redis:

Kelebihan: prestasi tinggi, kelajuan membaca dan menulis yang cepat, mengurangkan tekanan membaca dan menulis pangkalan data

Kelemahan: pembangunan kompleks, data keselamatan tidak dapat dijamin Masalahnya ialah data akan hilang apabila redis hang Pada masa yang sama, jika data dalam redis tidak disegerakkan dalam masa, ia mungkin dihapuskan apabila memori redis diganti. Walau bagaimanapun, kami tidak perlu begitu tepat tentang data yang serupa, dan kehilangan sedikit data bukanlah masalah besar.

Berikut ialah pengenalan terperinci kepada fungsi serupa daripada tiga aspek berikut

•Redis cache design

•Reka bentuk pangkalan data

•Dayakan penyimpanan berterusan tugas berjadual ke pangkalan data

1 reka bentuk dan pelaksanaan cache Redis

Kami telah memperkenalkan cara mengintegrasikan Redis dalam artikel sebelumnya, di sini saya menang'. t ulangi penjelasan lagi. Kami faham bahawa apabila melakukan operasi serupa, data berikut perlu direkodkan: rekod terperinci pengguna yang disukai oleh pengguna lain dan rekod operasi serupa. Untuk memudahkan pertanyaan dan akses, saya menggunakan struktur Hash untuk storan Struktur storan adalah seperti berikut:

(1) Rekod terperinci pengguna yang disukai oleh pengguna lain: MAP_USER_LIKED ialah nilai utama. , dan disukai Id pengguna:: Seperti id pengguna difailkan, 1 atau 0 ialah nilai

(2) Statistik bilangan suka untuk pengguna: MAP_USER_LIKED_COUNT ialah nilai utama dan pengguna yang disukai id difailkan, count Sebahagian daripada kod untuk nilai

adalah seperti berikut

/**
* 将用户被其他用户点赞的数据存到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;
}

Struktur storan Redis adalah seperti yang ditunjukkan

Cara menggunakan Redis untuk melaksanakan fungsi serupa

Cara menggunakan Redis untuk melaksanakan fungsi serupa

2 , Reka bentuk pangkalan data

Di sini kita boleh mereka bentuk dua jadual sama seperti menyimpan terus data seperti itu ke pangkalan data:

(1) Rekod terperinci pengguna sedang disukai oleh pengguna lain: 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) Statistik bilangan suka untuk pengguna: 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 Dayakan penyimpanan berterusan tugas berjadual ke pangkalan data

Kami menggunakan Kuarza untuk melaksanakan tugas berjadual dan menggunakan Redis Data dalam disimpan dalam pangkalan data Untuk menunjukkan kesannya, kami boleh menetapkan data untuk disimpan sekali dalam satu minit atau dua minit, bergantung pada perniagaan tertentu. Dalam proses penyegerakan data, kita mesti menyemak data dalam Redis dalam pangkalan data dan membuang data pendua, supaya data kita akan lebih tepat.

Sebahagian kod adalah seperti berikut

//同步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);
        }
    });
}

Atas ialah kandungan terperinci Cara menggunakan Redis untuk melaksanakan fungsi serupa. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam