redis存储对象的过期设置在实际项目中的运用案例展示!经过前面的学习,我们已经基本上初步掌握了redis数据库存储对象的过期时间是如何设置的了。下面给大家展示一个具体的实际开发项目中用到业务场景。


在项目化生寺小程序游戏开发中,有道具:鲜花,香,油灯;为了方便开发,把这这些道具统一规划到了一张表内:tb_pro;

但是,尽管如此,他们彼此之间还是存在一些差异的,比如鲜花会存在枯萎的情况,这个就是涉及到了有效期的问题。但是香火,和油灯则没有这个需求。我们在数据表内增加了一个字段:

redis存储对象的过期设置在实际项目中的运用案例展示-LMLPHP

如图,既然涉及到了有效期(过期)的业务需求,这个商品本身,必须具备一个唯一的键值,才能和别的商品区分开。


比如客户在2024-02-03 16:00:00分下单购买了一束鲜花(加入了客户自己的背包中了);那么,背包中的这束鲜花,就已经开始加入到了我们的redis数据库中了。此时它已经开启了有效期(过期的机制了)。我们设置的鲜花道具过期时间是,72小时候过期(枯萎)。

枯萎后的鲜花,是不能继续使用的。我们需要修改它的status(状态从正常-0;改成1-枯萎。)

虽然通常情况下,客户下单购买鲜花道具后,都是会马上进行消费(使用-上供供花属于消费行为。鲜花道具的状态会变成:2-已用)。

redis存储对象的过期设置在实际项目中的运用案例展示-LMLPHP

如上所示,我们mysql数据库用户背包内存储的鲜花道具的状态,是否发生变化,取决于2件事。

第一:用户的消费 行为,可以触发状态的改变。

第二:redis数据库内过期了。也会触发状态的改变。但是这种改变,是被动的,我们还没有使用消息通知的模式。只有当用户去使用的时候,我们才会去被动的判定,状态是不是已经枯萎了。

当然了,代码层面是可以完善的。借助于定时器。定一个间隔,轮询redis内的数据过期情况,查询到了过期,就给后端发送通知去修改状态。

这是后话。


我们使用了java官方自带的uuid来实现鲜花道具的唯一key。

 public static void main(String[] args) {
            String uniqueKey = UUID.randomUUID().toString();
            System.out.println("Unique Key: " + uniqueKey);
    }

 redis存储对象的过期设置在实际项目中的运用案例展示-LMLPHP

它产生了一个字符串。

我们把它作为鲜花道具的唯一key。就可以在redis数据库内区别开了。


 redis存储对象的过期设置在实际项目中的运用案例展示-LMLPHP

如图,在tb_bag数据表内,我们存储了所有用户的背包信息。

里面可以看见有user_id(哪个用户);key_no(哪个鲜花);pro_id(产品自身的id);pro_name(产品的名字);pro_count(产品的数量);pro_type_id(产品的分类id,0-鲜花,1-灯,2-香火);

实际上,对于不具备有效期的产品类型,我们无需给它生成唯一键。之所以我们需要一个唯一键,目的就是为了计算该产品的有效期。


@Data
@Entity
@Table(name = "tb_pro")
public class Product {
    @javax.persistence.Id
    @org.springframework.data.annotation.Id
    @GeneratedValue(strategy= GenerationType.IDENTITY)//主键生成策略
    private Integer id;
    private String name;
    private Integer status;//状态:默认是0-正常,1-枯萎,2-已用
    private Integer life;//生命周期默认是72小时
    @Column(name = "life_end" ,nullable = true)
    private Integer lifeEnd;//生命周期结束值,初始为0
    private Integer price;//单价
    private Integer type;//产品种类:0-花,1-灯,2-香火
    private Integer source;//来源:默认是0-领取,1-购买,2-赠予
    @Column(name = "key_no",nullable = true)
    private String kyeNo;//唯一键.为了跟踪有效期

}

 如图,数据表对应的实体类。我们对不同的属性值和表内字段值进行了映射。


package com.yrl.managedemo.controller;

import com.yrl.managedemo.bean.Bag;
import com.yrl.managedemo.bean.Product;
import com.yrl.managedemo.bean.Result;
import com.yrl.managedemo.service.IBagService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/bag")
public class BagController {
    @Autowired
    private IBagService bagService;

    @GetMapping("/list")
    public Result<List<Bag>> getAllBag(){
        Result<List<Bag>> result = new Result<>();
        List<Bag> bagList = bagService.getAll();
        if(bagList.size()>0){
            result.setCode(200);
            result.setMsg("查询背包信息成功");
            result.setData(bagList);
            return  result;
        }else{
            result.setCode(500);
            result.setMsg("服务器异常");
            return  result;
        }
    }

    /**
     * 查询某一个用户的背包所有产品信息
     * @param id 用户id
     * @return
     */
    @GetMapping("/list/user")
    public Result<List<Bag>> getBagListByUserId(Integer id){
        Result<List<Bag>> result = new Result<>();
        List<Bag> userBagList = bagService.getBagListByUserId(id);
        if(userBagList.size()>0){
            result.setCode(200);
            result.setMsg("查询用户背包信息成功");
            result.setData(userBagList);
            return result;
        }else{
            result.setCode(500);
            result.setMsg("服务器异常");
            return  result;
        }
    }

    /**
     * 向背包中新增一条数据信息。
     * @param uid
     * @param product
     * @return
     */
    @PostMapping("/add")
    public Result addOneBagByUserId(Integer uid, Product product,Integer count){
        Result result = new Result();
        try{
            Bag bag = new Bag();
            //封装数据到对象中
            bag.setUserId(uid);
            bag.setKeyNo(product.getKyeNo());
            bag.setProCount(count);
            bag.setProId(product.getId());
            bag.setProName(product.getName());
            bag.setProTypeId(product.getType());
            bagService.addOneBag(bag);
            result.setCode(200);
            result.setMsg("新增一条背包信息成功");
            return result;
        }catch (Exception e){
            System.out.println(e.fillInStackTrace());
            result.setCode(500);
            result.setMsg("服务器异常");
            return  result;
        }


    }
}

如图是,背包控制器内的代码情况,

我们新增一条背包信息的时候,传递过来的产品信息是一个实体类的形式封装到了里面。里面已经有一个唯一key了。

它就是将来redis存储的时候,用了判定某个对象过期的关键所在。


/**
         * 设置某一个用户所拥有的某个产品的过期时间
         * @param uid 用户id
         * @param keyNo 产品的唯一键
         */
        @Test
        public void testAddFlower(Integer uid,String keyNo){
            Jedis  jedis= new Jedis("localhost",6379);
            //加入redis内部
            jedis.hset("keyNo","uid","uid");
            //设置过期时间 单位是秒。
            long endLife = 60*60*24*3;//72小时后过期。
            jedis.expire("keyNo",endLife);

        }

如图所示,我们设置了某一个用户,拥有的某一个产品的过期时间。

后期这个用户想使用这个产品时,会查询到,redis返回null.说明已经过期了.

02-08 12:09