redis存储对象的过期设置在实际项目中的运用案例展示!经过前面的学习,我们已经基本上初步掌握了redis数据库存储对象的过期时间是如何设置的了。下面给大家展示一个具体的实际开发项目中用到业务场景。
在项目化生寺小程序游戏开发中,有道具:鲜花,香,油灯;为了方便开发,把这这些道具统一规划到了一张表内:tb_pro;
但是,尽管如此,他们彼此之间还是存在一些差异的,比如鲜花会存在枯萎的情况,这个就是涉及到了有效期的问题。但是香火,和油灯则没有这个需求。我们在数据表内增加了一个字段:
如图,既然涉及到了有效期(过期)的业务需求,这个商品本身,必须具备一个唯一的键值,才能和别的商品区分开。
比如客户在2024-02-03 16:00:00分下单购买了一束鲜花(加入了客户自己的背包中了);那么,背包中的这束鲜花,就已经开始加入到了我们的redis数据库中了。此时它已经开启了有效期(过期的机制了)。我们设置的鲜花道具过期时间是,72小时候过期(枯萎)。
枯萎后的鲜花,是不能继续使用的。我们需要修改它的status(状态从正常-0;改成1-枯萎。)
虽然通常情况下,客户下单购买鲜花道具后,都是会马上进行消费(使用-上供供花属于消费行为。鲜花道具的状态会变成:2-已用)。
如上所示,我们mysql数据库用户背包内存储的鲜花道具的状态,是否发生变化,取决于2件事。
第一:用户的消费 行为,可以触发状态的改变。
第二:redis数据库内过期了。也会触发状态的改变。但是这种改变,是被动的,我们还没有使用消息通知的模式。只有当用户去使用的时候,我们才会去被动的判定,状态是不是已经枯萎了。
当然了,代码层面是可以完善的。借助于定时器。定一个间隔,轮询redis内的数据过期情况,查询到了过期,就给后端发送通知去修改状态。
这是后话。
我们使用了java官方自带的uuid来实现鲜花道具的唯一key。
public static void main(String[] args) {
String uniqueKey = UUID.randomUUID().toString();
System.out.println("Unique Key: " + uniqueKey);
}
它产生了一个字符串。
我们把它作为鲜花道具的唯一key。就可以在redis数据库内区别开了。
如图,在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.说明已经过期了.