redis——對項目的一些優化方案

      網友投稿 719 2025-04-06

      這是我們之前項目的業務流程,做一下簡單介紹。

      登錄:

      用戶輸入賬號、密碼、驗證碼。我們先判斷用戶輸入的驗證碼是不是我們session存的驗證碼,然后去查賬號密碼是否正確。

      如果登錄成功,發送給用戶一張憑證(ticket)。

      登錄后

      之后的每次請求,用戶攜帶ticket,服務器得到后,根據ticket去login_ticket表中查找登錄信息,并且根據登錄信息再查user表獲得更多的用戶信息。

      使用Redis存儲驗證碼

      - 驗證碼需要頻繁的訪問與刷新,對性能要求較高。

      - 驗證碼不需永久保存,通常在很短的時間后就會失效。

      - 分布式部署時,存在Session共享的問題。

      我們重構思路:進入登錄頁面會訪問驗證碼方法,此方法會自動生成一個驗證碼和圖片,將驗證碼和圖片輸出給瀏覽器,并且下發一個cookies,這個cookies里面存的是一段隨機數,這段隨機數作為key存在Redis里面(之前是存session),value就是驗證碼,并設置一個過期時間;

      //驗證碼

      @RequestMapping(path = "/kaptcha", method = RequestMethod.GET)

      public void getKaptcha(HttpServletResponse response/*, HttpSession session*/) {

      // 生成驗證碼

      String text = kaptchaProducer.createText();

      BufferedImage image = kaptchaProducer.createImage(text);

      // 將驗證碼存入session

      //session.setAttribute("kaptcha", text);

      //驗證碼的歸屬

      String owner= CommunityUtil.generateUUID();

      Cookie cookie=new Cookie("kaptchaOwner",owner);

      cookie.setMaxAge(60);

      cookie.setPath(contextPath);

      response.addCookie(cookie);

      //存入redis

      String redisKey= RedisKeyUtil.getKaptchaKey(owner);

      redisTemplate.opsForValue().set(redisKey,text,60, TimeUnit.SECONDS);

      // 將圖片輸出給瀏覽器

      response.setContentType("image/png");

      try {

      OutputStream os = response.getOutputStream();

      ImageIO.write(image, "png", os);

      } catch (IOException e) {

      logger.error("響應驗證碼失敗:" + e.getMessage());

      }

      }

      @RequestMapping(path = "/login",method = RequestMethod.POST)

      public String login(String username,String password,String code,boolean rememberme,

      Model model,/*HttpSession session,*/HttpServletResponse response,

      @CookieValue("kaptchaOwner") String kaptchaOwner){

      // 檢查驗證碼

      //String kaptcha = (String) session.getAttribute("kaptcha");

      String kaptcha=null;

      if(StringUtils.isNotBlank(kaptchaOwner)){

      String redisKey=RedisKeyUtil.getKaptchaKey(kaptchaOwner);

      kaptcha=(String) redisTemplate.opsForValue().get(redisKey);

      }

      if(StringUtils.isBlank(kaptcha) || StringUtils.isBlank(code) || !kaptcha.equalsIgnoreCase(code)){

      model.addAttribute("codeMsg", "驗證碼不正確!");

      return "/site/login";

      }

      // 檢查賬號,密碼

      int expiredSeconds = rememberme ? REMEMBER_EXPIRED_SECONDS : DEFAULT_EXPIRED_SECONDS;

      Map map = userService.login(username, password, expiredSeconds);

      redis——對項目的一些優化方案

      if (map.containsKey("ticket")) {

      Cookie cookie = new Cookie("ticket", map.get("ticket").toString());

      cookie.setPath(contextPath);

      cookie.setMaxAge(expiredSeconds);

      response.addCookie(cookie);

      return "redirect:/index";

      } else {

      ...

      }

      }

      使用Redis存儲登錄憑證

      - 處理每次請求時,都要查詢用戶的登錄憑證,訪問的頻率非常高。

      登錄時不存MySQL里,存redis里

      public Map login(String username,String password,int expiredSeconds){

      Map map=new HashMap<>();

      // 生成登錄憑證

      LoginTicket loginTicket = new LoginTicket();

      loginTicket.setUserId(user.getId());

      loginTicket.setTicket(CommunityUtil.generateUUID());

      loginTicket.setStatus(0);

      loginTicket.setExpired(new Date(System.currentTimeMillis() + expiredSeconds * 1000));

      //loginTicketMapper.insertLoginTicket(loginTicket);

      String redisKey= RedisKeyUtil.getTicketKey(loginTicket.getTicket());

      redisTemplate.opsForValue().set(redisKey,loginTicket);

      ...

      }

      查找

      退出時也是改redis

      public void logout(String ticket) {

      //loginTicketMapper.updateStatus(ticket, 1);

      String redisKey= RedisKeyUtil.getTicketKey(ticket);

      LoginTicket loginTicket=(LoginTicket) redisTemplate.opsForValue().get(redisKey);

      loginTicket.setStatus(1);

      redisTemplate.opsForValue().set(redisKey,loginTicket);

      }

      使用Redis緩存用戶信息

      - 處理每次請求時,都要根據憑證查詢用戶信息,訪問的頻率非常高。

      緩存用戶信息:因為會經常根據userid來查詢user對象,所以使用redis來緩存提高服務器性能。使用redis的String類型,存入user對象,會自動將整個對象轉換成json字符串,同時設置過期時間;

      取值:優先從redis中取,取不到的時候從mysql中取,并將數據初始化到redis中

      更新:更新的時候先更新mysql中的值,然后清除緩存數據;

      // 1.優先從緩存中取值

      private User getCache(int userId) {

      String redisKey = RedisKeyUtil.getUserKey(userId);

      return (User) redisTemplate.opsForValue().get(redisKey);

      }

      // 2.取不到時初始化緩存數據

      private User initCache(int userId) {

      User user = userMapper.selectById(userId);

      String redisKey = RedisKeyUtil.getUserKey(userId);

      redisTemplate.opsForValue().set(redisKey, user, 3600, TimeUnit.SECONDS);

      return user;

      }

      // 3.數據變更時清除緩存數據

      private void clearCache(int userId) {

      String redisKey = RedisKeyUtil.getUserKey(userId);

      redisTemplate.delete(redisKey);

      }

      public User findUserById(int id) {

      // return userMapper.selectById(id);

      User user = getCache(id);

      if (user == null) {

      user = initCache(id);

      }

      return user;

      }

      public int updateHeader(int userId, String headerUrl) {

      //return userMapper.updateHeader(userId, headerUrl);

      int rows=userMapper.updateHeader(userId, headerUrl);

      clearCache(userId);

      return rows;

      }

      Redis

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:怎么設置首字下沉(wps怎么設置首字下沉)
      下一篇:DC/OS 1.12 正式發布—支持多集群Kubernetes與數據服務的跨云部署
      相關文章
      国产亚洲精午夜久久久久久 | 亚洲大尺度无码无码专区| 色天使亚洲综合一区二区| 国产午夜亚洲精品国产| 亚洲天堂2017无码中文| 亚洲国产精品综合一区在线| 亚洲综合久久1区2区3区| 在线观看亚洲人成网站| 精品日韩亚洲AV无码| 亚洲黄网在线观看| 亚洲最大中文字幕| 亚洲xxxxxx| 亚洲综合伊人制服丝袜美腿| 亚洲人成网男女大片在线播放| 亚洲国产夜色在线观看| 亚洲最大成人网色香蕉| 亚洲一卡2卡三卡4卡无卡下载| 亚洲午夜精品一区二区麻豆| 亚洲av日韩专区在线观看| 校园亚洲春色另类小说合集| 午夜在线亚洲男人午在线| 亚洲人成网站在线观看青青| 日日噜噜噜噜夜夜爽亚洲精品| 亚洲色欲一区二区三区在线观看| 亚洲精品夜夜夜妓女网| 人人狠狠综合久久亚洲婷婷| 亚洲va在线va天堂va四虎| 亚洲激情视频网站| 中文字幕亚洲男人的天堂网络| 亚洲日产乱码一二三区别| 久久精品熟女亚洲av麻豆| 亚洲国产精品无码久久青草| 国产精品亚洲精品日韩已方 | 亚洲中文无码线在线观看| 国内精品久久久久影院亚洲| 亚洲国产成人精品无码区花野真一| 国产精品亚洲av色欲三区| 亚洲人成人网站在线观看| 亚洲成AV人在线播放无码| 亚洲综合激情九月婷婷| 亚洲国产日韩精品|