redis缓存商品库存减压

redis缓存库存

Redis预减库存:主要思路减少对数据库的访问,之前的减库存,直接访问数据库,读取库存,当高并发请求到来的时候,大量的读取数据有可能会导致数据库的崩溃。

我们主要是通过这几点来实现的:
1、系统初始化的时候,将商品库存加载到Redis 缓存中保存,并不是需要先请求一次才能缓存
2、.收到请求的时候,现在Redis中拿到该商品的库存值,进行库存预减,如果减完之后库存不足,直接返回逻辑错误,减少对数据库的访问
3、将请求入队,立即给前端返回一个值,表示正在排队中,然后进行秒杀逻辑,减库存–>下订单–>写入秒杀订单,成功了就返回成功,流程只要有一个错误就返回失败,前端同时轮询

首先我们需要实现InitializingBean接口,InitializingBean接口为bean提供了初始化方法的方式,它就包括afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候会执行该方法。

	/**
	 *	系统初始化后就将所有商品库存放入 缓存
	 * */
	public void afterPropertiesSet() throws Exception {
		List<GoodsVo> goodsList = goodsService.listGoodsVo();
		if(goodsList == null) {
			return;
		}
		for(GoodsVo goods : goodsList) {
			redisService.set(GoodsKey.getMiaoshaGoodsStock, ""+goods.getId(), goods.getStockCount());
			localOverMap.put(goods.getId(), false);//先初始化 每个商品都是false 就是还有库存
		}
	}

这就实现了我们系统启动就把所有缓存加载完毕,然后我们通过操作redis来实现预减库存

然后当我们的并发量够大,redis的压力页很大,然后我们可以通过map集合标记缓存,减少redis服务器的压力

1、生成一个map,并在初始化的时候,将所有商品的id为键,标记false 存入map中。
2、在预减库存之前,从map中取标记,若标记为false,说明库存,还有,
3、预减库存,当遇到库存不足的时候,将该商品的标记置为true,表示该商品的库存不足。
这样,下面的所有请求,将被拦截,无需访问redis进行预减库存。

private HashMap<Long, Boolean> localOverMap =  new HashMap<Long, Boolean>();
	@RequestMapping(value="/{path}/do_miaosha", method=RequestMethod.POST)
	@ResponseBody
	public Result<Integer> miaosha(HttpServletRequest request, HttpServletResponse response,
								   Model model,MiaoshaUser user,
								   @RequestParam("goodsId")long goodsId,
								   @PathVariable("path") String path) {
		model.addAttribute("user", user);
		//如果用户为空,则返回至登录页面
		if(user == null) {
			return Result.error(CodeMsg.SESSION_ERROR);
		}
		//验证path
		boolean check = miaoshaService.checkPath(user, goodsId, path);
		if(!check){
			return Result.error(CodeMsg.REQUEST_ILLEGAL);
		}
		//内存标记,从map取值判断,减少redis访问
		boolean over = localOverMap.get(goodsId);
		if(over) {
			return Result.error(CodeMsg.MIAO_SHA_OVER);
		}
		//预减库存
		long stock = redisService.decr(GoodsKey.getMiaoshaGoodsStock, ""+goodsId);//10
		if(stock < 0) {
			localOverMap.put(goodsId, true);
			return Result.error(CodeMsg.MIAO_SHA_OVER);
		}
		//判断是否已经秒杀到了
		MiaoshaOrder order = orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(), goodsId);
		if(order != null) {
			return Result.error(CodeMsg.REPEATE_MIAOSHA);
		}
		//入队
		MiaoshaMessage mm = new MiaoshaMessage();
		mm.setUser(user);
		mm.setGoodsId(goodsId);
		sender.sendMiaoshaMessage(mm);
		//返回0代表排队中
		return Result.success(0);
	}

redis给数据库减轻压力,利用map标记库存给redis减轻压力

end…

发布了142 篇原创文章 · 获赞 909 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/qq_43517653/article/details/103847529
今日推荐