快销商品库存如何创建缓存

该博客介绍了如何使用Redis有序集合(sorted set)来管理商品库存,包括按批次查询库存和下单时的库存扣减操作。通过ZADD命令写入批次库存数据,ZRANGE命令查询指定批次范围的库存,并使用ZREM删除数据。在下单时,通过负数记录实现库存扣减,处理了库存重复扣除的问题。
摘要由CSDN通过智能技术生成

场景业务:一个商品在不同的地区的仓库的库存数量不同,而且会有对应不同批次,不同批次对应不同仓库商品,数量不同。

变量: 商品id   , 库存地址 , 批次( 用户来查询时是个区间值 例如:  20210901-202109010 )

示例数据:

商品id库存地址批次库存数量
11000020210901100
110000200

同一个商品 分为带批次的和不带批次的商品 。

用户下单看到的商品库存有两种查看方式:

        1、直接查所有商品的库存数(包含带批次的)

        2、商品按 批次 搜索(这个批次是变动的 如:20210901-20210910 或者 20210901-20210980)

那建立缓存的话第一种没啥问题很简单的键值对就可以满足查询的需求。

第二种按批次搜索应该怎么建立缓存的数据结构?

正文:

这里采用的Redis 服务来创建缓存

任何涉及到取值范文的查询第一个想起的存储结构肯定是 Redis 有序集合(sorted set)

下面是需要用到的命令行:

keyName :键名称

语法描述 :  ZRANGE keyName  [开始score] [结束score]   作用:查询在这个区间的值这个 分数是double类型
 
 示例: ZRANGE keyName  0 20210721 
 
语法描述 : ZADD keyName score value   					作用:写入值  值是字符串类型

 示例:	ZADD keyName 100  -1	
 
语法描述 : ZREM keyName value							作用: 删除对应的值

 示例:	ZREM keyName  -1	

注意:这个数据集是set 是不能存储重复数据的

下面说说业务实现逻辑:

1、首先通过 Zadd 将业务数据写入到redis, 批次数据在数据库是不会重复的 可以作为 score 存储

写入缓存部分代码:

	// 查询批次商品库存数据 写入缓存   
		List<Map<String, Object>> findStockPiCiAll = mtlSysItemsSnRepository.findStockPiCiAll();
		String keyPrex1 = "pici_stock_on_hand";
		String delkeyPici =  keyPrex1+"*";
		redisService.redisDeleteByPrex(delkeyPici);
		findStockPiCiAll.forEach(item -> {
			String key = String.format(keyPrex1+"%s_%s", item.get("INVENTORY_ITEM_ID"), item.get("FROM_STORAGE_ADDRESS_CODE"));
			Double lot_number = Double.parseDouble(item.get("lot_number").toString());
			redisTemplate.opsForZSet().add(key,item.get("AVAILABLE_QTY").toString(), lot_number);
		}); 
		

2、查询批次通过 ZRANGE 获取一个 String列表 将数据累加起来可以得到对应批次的库存数据

获取批次库存数据部分代码:

/**
	 * 根据批次信息获取库存
	 * @param sourceId
	 * @param deliverCompany 发货方
	 * @param lot_from1  批次从
	 * @param lot_to1	批次至
	 * @return
	 */
	private Integer getPiCiStock(String sourceId, String deliverCompany,String lot_from1,String lot_to1) {
		String keyPrex1 = "pici_stock_on_hand";
		// 批次库存缓存名称
		String key = String.format(keyPrex1+"%s_%s",sourceId, deliverCompany);
		int count = 0;
		int lot_from = Integer.parseInt(lot_from1);
		int lot_to =Integer.parseInt(lot_to1);
	  
		Set redisGetZadd =redisTemplate.opsForZSet().rangeByScore(key, lot_from, lot_to);
		if (!CollectionUtils.isEmpty(redisGetZadd)) {
			for (Object object : redisGetZadd) {
				Double parseDouble = Double.parseDouble(object.toString());
				count = count+parseDouble.intValue();
			}
		}
		return count;
	}

3、下单业务当订单完成,要对库存做扣减,通过 Zadd 添加一条负数记录(这里要注意的是:下单时用户的购买的商品数量可能相同 但是set 无法插入两条一样的数据,这里需要特殊处理插入前移除相同的主键 如果返回1这说明存在一样的数据 这样新插入的数据就要乘2)

部分代码

	// 带批次商品扣减数量
					Long quantity = 0-salesBillLine2.getQuantity();
					String keyPrex1 = "pici_stock_on_hand";
					// 批次库存缓存名称
					String key = String.format(keyPrex1+"%s_%s",sourceId, deliverCompany);
					
					Long rangeRemove =redisTemplate.opsForZSet().remove(key, quantity.toString());
					if (rangeRemove.intValue()>0) {
						quantity = quantity*2;
						// 扣减下单库存     加一条负数记录
						redisTemplate.opsForZSet().add(key, quantity.toString(), Double.parseDouble(lotNumberFrom));
					}else {
						// 扣减下单库存     加一条负数记录
						redisTemplate.opsForZSet().add(key, quantity.toString(), Double.parseDouble(lotNumberFrom));
					}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值