缓存用户信息

因为用户信息不是经常需要修改的 可以将用户信息存储至Redis中 不但可以减轻数据库的压力 而且可以更快的将用户的数据查询出来

在BaseController中顶一个redis字段用于标识用户信息

    protected static final String REDIS_USER_CACHE = "redis_user_cache";

缓存思路:

  1. 从redis中根据id查询用户信息 如果有用户信息 直接使用Jackson将json转换成用户信息对象返回
  2. 若redis中无数据 从数据库中查询用户信息 并保存至Redis中

    private AppUser getUser(String userId) {
        String redisUser = redisOperator.get(REDIS_USER_CACHE + ":" + userId);

        AppUser appUser = null;

        if (StringUtils.isBlank(redisUser)) {
            appUser = userService.getUser(userId);
            String appUserJson = JsonUtil.objectForJson(appUser);
            redisOperator.set(REDIS_USER_CACHE + ":" + userId, appUserJson);
        } else {
            appUser = JsonUtil.jsonToObject(redisUser, AppUser.class);
        }

        return appUser;
    }

在查询用户信息时调用此方法即可

    @Override
    public GraceJSONResult getUserInfo(String userId) {
        if (StringUtils.isBlank(userId)) {
            return new GraceJSONResult(ResponseStatusEnum.UN_LOGIN);
        }

        AccountBasicInfoVO accountBasicInfoVO =
                new AccountBasicInfoVO();

        AppUser user = getUser(userId);

        BeanUtils.copyProperties(user, accountBasicInfoVO);

        return GraceJSONResult.ok(accountBasicInfoVO);
    }

    @Override
    public GraceJSONResult getAccountInfo(String userId) {
        if (StringUtils.isBlank(userId)) {
            return GraceJSONResult.errorCustom(ResponseStatusEnum.UN_LOGIN);
        }
        AppUser appUser = getUser(userId);

        AppUserVO appUserVO = new AppUserVO();

        BeanUtils.copyProperties(appUser, appUserVO);

        return GraceJSONResult.ok(appUserVO);
    }

当用户信息进行更新时 只更改了数据库中的信息 而redis中的信息还是以前未修改前的脏数据 所以 更新时要将新数据查询后覆盖到redis中

业务思路:

  1. 进行用户信息修改操作
  2. 修改完毕后根据用户id查询到用户 并覆盖到redis中
   @Override
   @Transactional
   public void updateUserInfo(UpdateUserBO updateUserBO) {
      AppUser user = new AppUser();

      BeanUtils.copyProperties(updateUserBO, user);
      user.setActiveStatus(UserStatus.ACTIVE.type);

      int resultNum = userMapper.updateById(user);

      if (resultNum != 1) {
         GraceException.display(ResponseStatusEnum.USER_UPDATE_ERROR);
      }

      // 更新用户时 将更新后的数据查询出来并覆盖到redis中
      AppUser updateUser = this.getUser(updateUserBO.getId());
      redisOperator.set(REDIS_USER_CACHE + ":" + updateUserBO.getId(), JsonUtil.objectForJson(updateUser));

   }

双写数据不一致的问题
当进行用户信息更新操作时 遇到网络 问题或其他问题而导致只更新了数据库 而未将数据写入redis中 这样就形成了数据不一致的问题
解决方法: 进行更新操作时

  1. 先将reids中的旧数据删除
  2. 在修改数据库之后 再将新数据写入redis中

当用户发送多个请求时 旧缓存删除成功但是新数据还未来得及更新到数据库中 读缓存时发现redis中无数据 而想数据库中查询 查到的是未修改的旧数据
解决方法:

  1. 先将缓存删除
  2. 将数据库更新
  3. 线程等待一段时间 再次淘汰缓存数据 用于别的请求请求完成 避免读取脏数据
   @Override
   @Transactional
   public void updateUserInfo(UpdateUserBO updateUserBO) {
      // 删除redis数据
      redisOperator.del(REDIS_USER_CACHE + ":" + updateUserBO.getId());

      AppUser user = new AppUser();

      BeanUtils.copyProperties(updateUserBO, user);
      user.setActiveStatus(UserStatus.ACTIVE.type);

      int resultNum = userMapper.updateById(user);

      if (resultNum != 1) {
         GraceException.display(ResponseStatusEnum.USER_UPDATE_ERROR);
      }



      // 更新用户时 将更新后的数据查询出来并覆盖到redis中
      AppUser updateUser = this.getUser(updateUserBO.getId());
      redisOperator.set(REDIS_USER_CACHE + ":" + updateUserBO.getId(), JsonUtil.objectForJson(updateUser));

      try {
         Thread.sleep(100);
         redisOperator.del(REDIS_USER_CACHE + ":" + updateUserBO.getId());
      } catch (InterruptedException e) {
         e.printStackTrace();
      }

   }
posted @   RainbowMagic  阅读(358)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示