快捷搜索:  汽车  科技

redis 缓存什么数据(Redis只会用缓存20种妙用让同事直呼惊艳)

redis 缓存什么数据(Redis只会用缓存20种妙用让同事直呼惊艳)寄快递、网购的时候,查询物流信息,都会给我们展示xxx时候,快递到达什么地方了,这就是一个典型的时间线列表;# 购物车添加单个商品 127.0.0.1:6379> HSET sc:u1 c001 1 (integer) 1 # 购物车添加多个商品 127.0.0.1:6379> HMSET sc:u1 c002 1 coo3 2 OK # 添加商品购买数量 127.0.0.1:6379> HINCRBY sc:u1 c002 1 (integer) 2 # 减少商品的购买数量 127.0.0.1:6379> HINCRBY sc:u1 c003 -1 (integer) 1 # 获取单个的购买数量 127.0.0.1:6379> HGET sc:u1 c002 "2" # 获取购物车的商品数量 127.0.0.1:6379> HLEN s

假如现在iphone 100 、华为mate 5000 已发布,在各大商城上线;下面就通过 Redis 的 set 来实现上述的商品筛选功能;

功能所需命令

  • SADD key member [member …]:添加一个或多个元素
  • SINTER key [key …]:返回给定所有集合的交集
Redis-cli 客户端测试

# 将iphone100 添加到品牌为苹果的集合 127.0.0.1:6379> sadd brand:apple iphone100 (integer) 1 # 将meta5000 添加到品牌为苹果的集合 127.0.0.1:6379> sadd brand:huawei meta5000 (integer) 1 # 将 meta5000 iphone100 添加到支持5T内存的集合 127.0.0.1:6379> sadd ram:5t iphone100 meta5000 (integer) 2 # 将 meta5000 添加到支持10T内存的集合 127.0.0.1:6379> sadd ram:10t meta5000 (integer) 1 # 将 iphone100 添加到操作系统是iOS的集合 127.0.0.1:6379> sadd os:ios iphone100 (integer) 1 # 将 meta5000 添加到操作系统是Android的集合 127.0.0.1:6379> sadd os:android meta5000 (integer) 1 # 将 iphone100 meta5000 添加到屏幕为6.0-6.29的集合中 127.0.0.1:6379> sadd screensize:6.0-6.29 iphone100 meta5000 (integer) 2 # 筛选内存5T、屏幕在6.0-6.29的机型 127.0.0.1:6379> sinter ram:5t screensize:6.0-6.29 1) "meta5000" 2) "iphone100" # 筛选内存10T、屏幕在6.0-6.29的机型 127.0.0.1:6379> sinter ram:10t screensize:6.0-6.29 1) "meta5000" # 筛选内存5T、系统为iOS的机型 127.0.0.1:6379> sinter ram:5t screensize:6.0-6.29 os:ios 1) "iphone100" # 筛选内存5T、屏幕在6.0-6.29、品牌是华为的机型 127.0.0.1:6379> sinter ram:5t screensize:6.0-6.29 brand:huawei 1) "meta5000" 18购物车

商品缓存

电商项目中,商品消息,都会做缓存处理,特别是热门商品,访问用户比较多,由于商品的结果比较复杂,店铺信息,产品信息,标题、描述、详情图,封面图;为了方便管理和操作,一般都会采用 Hash 的方式来存储(key为商品ID,field用来保存各项参数,value保存对于的值)

购物车

当商品信息做了缓存,购物车需要做的,就是通过Hash记录商品ID,以及需要购买的数量(其中key为用户信息,field为商品ID,value用来记录购买的数量) ;

功能所需命令

  • HSET key field value : 将哈希表 key 中的字段 field 的值设为 value ;
  • HMSET key field1 value1 [field2 value2 ] :同时将多个 field-value (域-值)对设置到哈希表 key 中。
  • HGET key field:获取存储在哈希表中指定字段的值。
  • HGETALL key :获取在哈希表中指定 key 的所有字段和值
  • HINCRBY key field increment :为哈希表 key 中的指定字段的整数值加上增量 increment 。
  • HLEN key:获取哈希表中字段的数量
Redis-cli 客户端测试

# 购物车添加单个商品 127.0.0.1:6379> HSET sc:u1 c001 1 (integer) 1 # 购物车添加多个商品 127.0.0.1:6379> HMSET sc:u1 c002 1 coo3 2 OK # 添加商品购买数量 127.0.0.1:6379> HINCRBY sc:u1 c002 1 (integer) 2 # 减少商品的购买数量 127.0.0.1:6379> HINCRBY sc:u1 c003 -1 (integer) 1 # 获取单个的购买数量 127.0.0.1:6379> HGET sc:u1 c002 "2" # 获取购物车的商品数量 127.0.0.1:6379> HLEN sc:u1 (integer) 3 # 购物车详情 127.0.0.1:6379> HGETALL sc:u1 1) "c001" 2) "1" 3) "c002" 4) "2" 5) "coo3" 6) "2" 19定时取消订单(key过期监听)

电商类的业务,一般都会有订单30分钟不支付,自动取消的功能,此时就需要用到定时任务框架,Quartz、xxl-job、elastic-job 是比较常用的 Java 定时任务;我们也可以通过 Redis 的定时过期、以及过期key的监听,来实现订单的取消功能;

  • Redis key 过期提醒配置修改 redis 相关事件配置。找到 redis 配置文件 redis.conf,查看 notify-keyspace-events 配置项,如果没有,添加 notify-keyspace-events Ex,如果有值,则追加 Ex,相关参数说明如下:
    • K:keyspace 事件,事件以 keyspace@ 为前缀进行发布
    • E:keyevent 事件,事件以 keyevent@ 为前缀进行发布
    • g:一般性的,非特定类型的命令,比如del,expire,rename等
    • $:字符串特定命令
    • l:列表特定命令
    • s:集合特定命令
    • h:哈希特定命令
    • z:有序集合特定命令
    • x:过期事件,当某个键过期并删除时会产生该事件
    • e:驱逐事件,当某个键因 maxmemore 策略而被删除时,产生该事件
    • A:g$lshzxe的别名,因此”AKE”意味着所有事件
  • 添加RedisKeyExpirationListener的监听import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.redis.connection.RedisConnectionFactory;
    import org.springframework.data.redis.listener.RedisMessageListenerContainer;
    @Configuration
    public class RedisListenerConfig {
    @Bean
    RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
    RedisMessageListenerContainer container = new RedisMessageListenerContainer();
    container.setConnectionFactory(connectionFactory);
    return container;
    }
    }
    KeyExpirationEventMessageListener 接口监听所有 db 的过期事件 keyevent@*:expired"package com.ehang.redis.config;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.data.redis.connection.Message;
    import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
    import org.springframework.data.redis.listener.RedisMessageListenerContainer;
    import org.springframework.stereotype.Component;
    /**
    * 监听所有db的过期事件__keyevent@*__:expired"
    *
    * @author 一行Java
    * @title: RedisKeyExpirationListener
    * @projectName ehang-spring-boot
    * @description: TODO
    * @date 2022/8/5 16:36
    */
    @Component
    @Slf4j
    public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {
    public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
    super(listenerContainer);
    }
    /**
    * 针对 redis 数据失效事件,进行数据处理
    *
    * @param message
    * @param pattern
    */
    @Override
    public void onMessage(Message message byte[] pattern) {
    // 获取到失效的 key,进行取消订单业务处理
    // 由于这里是监听了所有的key,如果只处理特定数据的话,需要做特殊处理
    String expiredKey = message.toString();
    log.info("过期的Key:{}" expiredKey);
    }
    }
  • 测试为了快速验证效果,这里 将过期时间调整为2秒;注意,由于过期之后,Redis中的Key已经不存在了,因此,一定要将订单号作为key,不能作为值保存,否则监听到过期Key之后,将拿不到过期的订单号;
  • 不推荐使用基于这一套机制,确实能够实现订单的超时取消,但是还是不太建议使用,这里仅作为一个思路;原因主要有以下几个:
  • redis 的过期删除策略是采用定时离线扫描,或者访问时懒性检测删除,并没有办法保证时效性,有可能key已经到期了,但Redis并没有扫描到,导致通知的延迟;
  • 消息发送即忘(fire and forget),并不会保证消息的可达性,如果此时服务不在线或者异常,通知就再也收不到了;
20物流信息(时间线)

寄快递、网购的时候,查询物流信息,都会给我们展示xxx时候,快递到达什么地方了,这就是一个典型的时间线列表;

redis 缓存什么数据(Redis只会用缓存20种妙用让同事直呼惊艳)(1)

数据库的做法,就是每次变更就插入一条带时间的信息记录,然后根据时间和ID(ID是必须的,如果出现两个相同的时间,单纯时间排序,会造成顺序不对),来排序生成时间线;

我们也可以通过 Redis 的 List 来实现时间线功能,由于 List 采用的是双向链表,因此升序,降序的时间线都能正常满足;

  • RPUSH key value1 [value2]:在列表中添加一个或多个值,(升序时间线)
  • LPUSH key value1 [value2]:将一个或多个值插入到列表头部(降序时间线)
  • LRANGE key start stop:获取列表指定范围内的元素

Redis-cli 客户端测试

  • 升序127.0.0.1:6379> RPUSH time:line:asc 20220805170000
    (integer) 1
    127.0.0.1:6379> RPUSH time:line:asc 20220805170001
    (integer) 2
    127.0.0.1:6379> RPUSH time:line:asc 20220805170002
    (integer) 3
    127.0.0.1:6379> LRANGE time:line:asc 0 -1
    1) "20220805170000"
    2) "20220805170001"
    3) "20220805170002"
  • 降序127.0.0.1:6379> LPUSH time:line:desc 20220805170000
    (integer) 1
    127.0.0.1:6379> LPUSH time:line:desc 20220805170001
    (integer) 2
    127.0.0.1:6379> LPUSH time:line:desc 20220805170002
    (integer) 3
    127.0.0.1:6379> LRANGE time:line:desc 0 -1
    1) "20220805170002"
    2) "20220805170001"
    3) "20220805170000"

好了,关于Redis 的妙用,就介绍到这里;有了这些个场景的运用,下次再有面试官问你,Redis除了缓存还做过什么,相信聊上个1把小时,应该不成问题了。

猜您喜欢: