springboot+redis+mysql+quartz-通过Java操作redis的KEYS*命令获取缓存数据定时更新数据库

文章介绍了一个使用Redis缓存点赞数据,通过Quartz定时任务将数据持久化到MySQL数据库的过程。关键步骤包括从Redis的ZSet中获取点赞用户ID,利用Map存储,然后更新到数据库的blog_like表中,其中赞的数量存储在like_number字段。文章讨论了使用KEYS命令的不足,并推荐使用SCAN命令以减少对Redis的影响。
摘要由CSDN通过智能技术生成

代码讲解:

3-点赞功能-定时持久化到数据库(pipeline+lua)-完善过程2_哔哩哔哩_bilibili

https://www.bilibili.com/video/BV1w14y1o7BV

本文章代码:

blogLike_schedule/like03 · xin麒/XinQiUtilsOrDemo - 码云 - 开源中国 (gitee.com)

https://gitee.com/flowers-bloom-is-the-sea/XinQiUtilsOrDemo/tree/master/blogLike_schedule/like03

数据表库在:

https://gitee.com/flowers-bloom-is-the-sea/XinQiUtilsOrDemo/tree/master/blogLike_schedule

一、目标:

缓存数据存储着键名以BLOG_LIKED_KEY开头的zset数据,

zset数据的键类似于BLOG_LIKED_KEYid,里面的id是数据库里博客的id。

zset的value是点赞的用户id,已经是userId

zset的score是该点赞用户点赞的时间戳。

目标:通过定时任务将所有博客的点赞信息全部更新到数据库里。

数据库有一张名为blog_like的博客数据表:

有一个like_list字段,这个字段要存储的就是缓存返回来的该篇博客的所有点赞信息。

like_number是通过该篇博客点赞用户数量计算得来。

具体是通过com.xinqi.service.impl.BlogServiceImpldurableToDatabaseByBlogIdAndMap的方法:

    private void durableToDatabaseByBlogIdAndMap(Map<String,String> userIdWithTime,Long id){
        //什么都没有那肯定不操作
        if (userIdWithTime == null || userIdWithTime.size() == 0) return;

        String stringIds = userIdWithTime.toString();

        String updateSql =  "like_list = " + "'" + stringIds + "' ," +
                "like_number = " + userIdWithTime.size();
        boolean isSuccess = update()
                .setSql(updateSql)
                .eq("id", id)
                .update();
    }

二、实现过程:

1、重要依赖:

<!--1.先引入依赖-->
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.2.1</version>
        </dependency>

2、写好要执行的内容,定时任务要执行的内容在executeInternal方法里:

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xinqi.entity.Blog;
import com.xinqi.service.BlogService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.quartz.QuartzJobBean;

import java.util.Set;
@Slf4j//2、创建一个任务类
public class LikeTask extends QuartzJobBean {
    @Autowired
    BlogService blogService;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    /**
     * 用来从redis中的hash中获取点赞缓存的键值对,间隔时间存入mysql
     * @param context
     * @throws JobExecutionException
     */
    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
       // 要执行的内容就写在这个函数中
        blogService.updateAllLikeListToDatabase();
    }

}

3、写好定时任务的配置类,两个bean都要在withIdentity里面传入参数:

import com.xinqi.task.LikeTask;
import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration//3、QuartzConfig{quartzDetail_1、quartzTrigger_1}
public class QuartzConfig {
    @Bean
    public JobDetail quartzDetail_1(){
        // withIdentity指定的是这个job的id
        return JobBuilder.newJob(LikeTask.class)
                .withIdentity("LIKE_TASK_IDENTITY")
                .storeDurably()
                .build();
    }


    @Bean
    public Trigger quartzTrigger_1(){ //触发器
        SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
                .withIntervalInSeconds(40)  //设置时间周期单位秒,是执行executeInternal方法的频率
//                .withIntervalInHours(2)  //两个小时执行一次
                .repeatForever();
        return TriggerBuilder.newTrigger().forJob(quartzDetail_1())
//                .forJob(quartzDetail_2())
                .withIdentity("LikeTask_TRENDS_TRIGGER")
                .withSchedule(scheduleBuilder)
                .build();
    }


}

以上定时任务已经配置好了。

4、接下来就是要去实现LikeTask.executeInternal里面的blogService这个类的blogService.updateAllLikeListToDatabase()方法:

//这里就执行缓存的所有博客的likeList入数据库吧
@Override
public void updateAllLikeListToDatabase(){
    String prefix = "BLOG_LIKED_KEY";
    Set<String> keys = stringRedisTemplate.keys(prefix.concat("*"));
    for (String key : keys) {
        Map<String, String> map = queryAllBlogLikesUserIdWithScoresByRedisKey(key);
        //get blogId
        Long blogId = Long.parseLong(key.substring(prefix.length(),key.length()));

        durableToDatabaseByBlogIdAndMap(map,blogId);
    }

}

ok了,就这样了,具体代码已在文章开头给出。

三、其他

对于以上,是有不足的,就是keys+前缀*扫描会导致redis会阻塞其他操作,还是缓存scan好一点,请看这篇:

其他类似的文章:

(108条消息) springboot+redis+mysql+quartz-通过Java操作redis的KEYS*命令获取缓存数据定时更新数据库_xin麒的博客-CSDN博客

(108条消息) springboot+redis+mysql+quartz-通过Java操作jedis定时使用lua脚本获取缓存数据并更新数据库_xin麒的博客-CSDN博客

(108条消息) lua脚本获取table类型-Java使用lua脚本操作redis获取zset元素的集合_xin麒的博客-CSDN博客

(108条消息) springboot+redis+mysql+quartz-通过Java操作jedis使用pipeline获取缓存数据定时更新数据库_xin麒的博客-CSDN博客

(108条消息) springboot+redis+mysql+quartz-通过Java操作jedis的scan命令获取缓存数据定时更新数据库_xin麒的博客-CSDN博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值