• 使用 Redis 缓存来实现用户最近浏览的商品列表


    一、如何使用 Redis 来缓存来实现最近浏览的商品列表?

    首先我们要确定一个两个点,最近浏览的商品肯定是一个一个的操作。

    那么就可以确定以下几个问题:

    1. 最近浏览的记录肯定是要有失效时间的

      这里可以使用缓存(Redis等),缓存可以设置失效时间(最大设置为一个月)。

      如果使用关系型数据库,还需要定时清楚,就很不符合实际需求。

    2. 最近浏览记录肯定是要有个数限制的,不可能记录所有的浏览记录

      如果使用Redis来实现的话,Redis 中有 LTRM 来修建,以保证存储的浏览条数。

    3. 需要在哪里添加保存浏览商品的方法。

      用户最近浏览的商品,肯定是要在用户打开商品详情页的时候才算浏览。

    4. 怎么保证每次添加的浏览的商品列表按照浏览的先后顺序排序?

      每次用户的浏览商品的ID,可以以用户的ID作为Key,以 List 作为 value,存储在Redis中,

      而 List 是有序的,并且,在使用 LRANGE 的时候还能保证先进后出,后进先出的原则,以

      达到排列在最前面的商品始终是当前最近浏览的商品。

    5. 怎么保证用户在连续浏览同一商品的时候,不会重复保存商品?

      这里可以使用 Redis 中的 LREM 来移除例表中与参数 value(该商品ID) 想等的元素。

      同时再使用 Lpush 重新再List 中插入最新浏览的商品。

    6. 读取缓存的时候,怎么保证分页?

      Redis 中的 LRANGE 可以指定获取指定长度的元素。

    7. 怎么区别 PC 和 移动端?

      可以让前端根据 PC 和 移动端传不同的code,后台区别code,在 key(用户ID)后面跟上

      特定的字符串来区别。

    二、下面是简单的实现思路
    1. 存储用户浏览的商品信息:

      用户在打开商品详情页的时候,以用户ID作为key,商品的Id作为值,以List的形式存到Redis中。

      在加入缓存之前,为了确保浏览商品的唯一性,每次添加之前,使用 LREM 将缓存 List 中的商品id去掉,以保证最新的浏览记录始终在最前面。

      在 Lpush 到 Redis 的list中之后,可以根据需求 保留List中多少条浏览记录

      最后添加缓存失效时间。

    2. 获取用户最近的浏览商品列表:

      根据key(用户ID)及分页数,来获取商品缓存。

    三、下面是截取的一段核心代码:
    1. 根据用户ID和商品Id存入到缓存中:

          /**
           * 存一个浏览商品信息
           *
           * @param historyPo
           */
          @PostMapping("/set")
          public void set(@Validated @RequestBody HistoryPo historyPo) {
              String key = getKey(historyPo.getCode(), historyPo.getUserId());
              /* 为了保证浏览商品的 唯一性,每次添加前,将list中该商品ID去掉,再加入,以保证其浏览的最新的商品在最前面 */
              redisService.lrem(key, 1L, historyPo);
              /* 将value push 到该key下的list中 */
              redisService.lpush(key, historyPo);
              /* 浏览记录存5条,五条以后切掉*/
              redisService.lTrim(key, 0L, 4L);
              /* 缓存时间为一个月 */
              redisService.expire(key, DEFAULT_EXPIRE);
          }
      
      
    2. 根据用户的ID,分页获取最近浏览的商品:

      	/**
           * 获取当前用户的浏览历史
           *
           * @param code
           * @param userId
           * @return
           */
      @GetMapping("/all/{code}/{userId}")
      public List<HistoryPo> query(@PathVariable("code") Integer code, @PathVariable("userId") Long userId) {
          String key = getKey(code, userId);
          //这里可支持分页 start and end
          return redisService.lrange(key, 0L, 9999L);
      
          /* 以下代码解决json反序列化之后集合不能操作问题(例如使用Stream)
              String key = getKey(code, userId);
              List<HistoryPo> lrange = redisService.lrange(key, 0L, 9999L);
              JavaType javaType = getCollectionType(LinkedList.class, HistoryPo.class);
              List<HistoryPo> lst = null;
              try {
                  lst = mapper.readValue(lrange.toString(), javaType);
              } catch (IOException e) {
                  e.printStackTrace();
              }
              */
      }
      

      项目完整地址:https://github.com/wengzi/others

  • 相关阅读:
    解题:POI 2006 Periods of Words
    解题:NOI 2014 动物园
    1483. 最高平均分
    1438. 较大分组的位置(回顾)
    1258. 漂亮子数组
    1903. 部门统计(回顾)
    1509. 柠檬水找零
    1451. 到最近的人的最大距离
    1425. 比较含退格的字符串
    1394. 山羊拉丁文
  • 原文地址:https://www.cnblogs.com/leizzige/p/12354527.html
Copyright © 2020-2023  润新知