使用Spring Boot实现Redis多数据库缓存

打印 上一主题 下一主题

主题 901|帖子 901|积分 2703

Redis多数据库存储实现用户行为缓存

在我的系统中,为了优化用户行为数据的存储与访问服从,我引入了Redis缓存,并将数据分布在不同的Redis数据库中。通过这种方式,可以淘汰单一数据库的负载,进步系统的整体性能。
紧张实现步骤


  • Redis配置

    • 配置两个Redis毗连工厂,分别用于存储Token和用户行为数据。
    • 创建对应的RedisTemplate实例,指定不同的毗连工厂及序列化方式。

  • 用户行为服务

    • 通过UserBehaviorService接口及实在现类UserBehaviorServiceImpl,实现对用户点赞、收藏、品评、浏览行为的记录。
    • 在操作数据库的同时,将用户行为数据存储到Redis中以进步读取服从。

  • Token拦截器

    • 使用TokenInterceptor类在每次请求前验证Token。
    • 验证通过后,将用户信息存储到ThreadLocal中,供后续操作使用。

代码实现

Redis配置类

  1. @Configuration
  2. public class RedisConfig {
  3.     @Value("${spring.data.redis.host}")
  4.     private String redisHost;
  5.     @Value("${spring.data.redis.port}")
  6.     private int redisPort;
  7.     @Value("${spring.data.redis.password}")
  8.     private String redisPassword;
  9.     @Bean(name = "tokenRedisConnectionFactory")
  10.     public RedisConnectionFactory tokenRedisConnectionFactory() {
  11.         RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(redisHost, redisPort);
  12.         config.setPassword(redisPassword);
  13.         config.setDatabase(0);
  14.         return new LettuceConnectionFactory(config);
  15.     }
  16.     @Bean(name = "userBehaviorRedisConnectionFactory")
  17.     public RedisConnectionFactory userBehaviorRedisConnectionFactory() {
  18.         RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(redisHost, redisPort);
  19.         config.setPassword(redisPassword);
  20.         config.setDatabase(1);
  21.         return new LettuceConnectionFactory(config);
  22.     }
  23.     @Bean(name = "redisTemplate")
  24.     public StringRedisTemplate redisTemplate(@Qualifier("tokenRedisConnectionFactory") RedisConnectionFactory redisConnectionFactory) {
  25.         StringRedisTemplate template = new StringRedisTemplate();
  26.         template.setConnectionFactory(redisConnectionFactory);
  27.         template.setKeySerializer(new StringRedisSerializer());
  28.         template.setValueSerializer(new StringRedisSerializer());
  29.         return template;
  30.     }
  31.     @Bean(name = "userBehaviorRedisTemplate")
  32.     public RedisTemplate<String, Map<String, Integer>> userBehaviorRedisTemplate(@Qualifier("userBehaviorRedisConnectionFactory") RedisConnectionFactory redisConnectionFactory) {
  33.         RedisTemplate<String, Map<String, Integer>> template = new RedisTemplate<>();
  34.         template.setConnectionFactory(redisConnectionFactory);
  35.         template.setKeySerializer(new StringRedisSerializer());
  36.         template.setValueSerializer(new Jackson2JsonRedisSerializer<>(Map.class));
  37.         return template;
  38.     }
  39. }
复制代码
用户行为服务实现类

  1. @Service
  2. public class UserBehaviorServiceImpl implements UserBehaviorService {
  3.     private static final long CACHE_EXPIRATION_DAYS = 1;
  4.     private static final String CACHE_PREFIX = "articleCounts:";
  5.     @Autowired
  6.     private UserBehaviorMapper userBehaviorMapper;
  7.     @Autowired
  8.     @Qualifier("userBehaviorRedisTemplate")
  9.     private RedisTemplate<String, Map<String, Integer>> userBehaviorRedisTemplate;
  10.     @Override
  11.     public void setLikeArticle(Likes likes) {
  12.         likes.setCreateTime(LocalDateTime.now());
  13.         Integer userId = ThreadLocalUtil.getUser("id");
  14.         if (userId != null) {
  15.             likes.setUserId(userId);
  16.         }
  17.         userBehaviorMapper.insertLike(likes);
  18.     }
  19.     @Override
  20.     public void setFavoriteArticle(Favorites favorites) {
  21.         favorites.setCreateTime(LocalDateTime.now());
  22.         Integer userId = ThreadLocalUtil.getUser("id");
  23.         if (userId != null) {
  24.             favorites.setUserId(userId);
  25.         }
  26.         userBehaviorMapper.insertFavorite(favorites);
  27.     }
  28.     @Override
  29.     public void setCommentArticle(Comments comments) {
  30.         comments.setCreateTime(LocalDateTime.now());
  31.         Integer userId = ThreadLocalUtil.getUser("id");
  32.         if (userId != null) {
  33.             comments.setUserId(userId);
  34.         }
  35.         userBehaviorMapper.insertComment(comments);
  36.     }
  37.     @Override
  38.     public void setViewArticle(Views views) {
  39.         views.setCreateTime(LocalDateTime.now());
  40.         Integer userId = ThreadLocalUtil.getUser("id");
  41.         if (userId != null) {
  42.             views.setUserId(userId);
  43.         }
  44.         userBehaviorMapper.insertView(views);
  45.     }
  46.     @Override
  47.     public Map<String, Integer> getArticleCounts(Integer articleId) {
  48.         String key = CACHE_PREFIX + articleId;
  49.         Map<String, Integer> counts = userBehaviorRedisTemplate.opsForValue().get(key);
  50.         if (counts == null) {
  51.             counts = fetchArticleCountsFromDB(articleId);
  52.             cacheArticleCounts(articleId, counts);
  53.         }
  54.         return counts;
  55.     }
  56.     private Map<String, Integer> fetchArticleCountsFromDB(Integer articleId) {
  57.         Map<String, Integer> counts = new HashMap<>();
  58.         counts.put("likesCount", userBehaviorMapper.selectLikesCount(articleId));
  59.         counts.put("favoritesCount", userBehaviorMapper.selectFavoritesCount(articleId));
  60.         counts.put("commentsCount", userBehaviorMapper.selectCommentsCount(articleId));
  61.         counts.put("viewsCount", userBehaviorMapper.selectViewsCount(articleId));
  62.         return counts;
  63.     }
  64.     private void cacheArticleCounts(Integer articleId, Map<String, Integer> counts) {
  65.         String key = CACHE_PREFIX + articleId;
  66.         userBehaviorRedisTemplate.opsForValue().set(key, counts, CACHE_EXPIRATION_DAYS, TimeUnit.DAYS);
  67.     }
  68. }
复制代码
Token拦截器

  1. @Component
  2. public class TokenInterceptor implements HandlerInterceptor {
  3.     @Autowired
  4.     private StringRedisTemplate redisTemplate;
  5.     @Override
  6.     public boolean preHandle(HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) throws Exception {
  7.         String token = request.getHeader("Authorization");
  8.         if (token == null || token.isEmpty()) {
  9.             response.setStatus(HttpStatus.UNAUTHORIZED.value());
  10.             return false;
  11.         }
  12.         try {
  13.             ValueOperations<String, String> operations = redisTemplate.opsForValue();
  14.             String redisToken = operations.get(token);
  15.             if (redisToken == null) {
  16.                 response.setStatus(HttpStatus.UNAUTHORIZED.value());
  17.                 return false;
  18.             }
  19.             Map<String, Object> claims = JwtUtil.parseToken(token);
  20.             ThreadLocalUtil.setUser(claims);
  21.             return true;
  22.         } catch (Exception e) {
  23.             response.setStatus(HttpStatus.UNAUTHORIZED.value());
  24.             return false;
  25.         }
  26.     }
  27.     @Override
  28.     public void postHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler, ModelAndView modelAndView) throws Exception {
  29.     }
  30.     @Override
  31.     public void afterCompletion(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler, Exception ex) throws Exception {
  32.         ThreadLocalUtil.remove();
  33.     }
  34. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

商道如狼道

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表