Parcourir la source

Merge branch 'index_cache_fix'

chenbiao il y a 7 mois
Parent
commit
9e4d3891d6

+ 521 - 363
netflix-web/src/main/java/com/cyksj/web/controller/goods/GoodsDonController.java

@@ -355,28 +355,48 @@ public class GoodsDonController {
      */
     @GetMapping("/get/register")
     public Result<List<RegisterGoodsDonView>> getRegisterGoodsDon() {
-        String registerCacheKey = RedisService.key.REGISTER_HOME_PAGE_CACHE.getName();
-        Object value = redisService.get(registerCacheKey);
-        if (value != null) {
+        try {
+            String registerCacheKey = RedisService.key.REGISTER_HOME_PAGE_CACHE.getName();
+            Object value = redisService.get(registerCacheKey);
+            if (value != null) {
+                try {
+                    List<RegisterGoodsDonView> list = Jsons.parseList(value, RegisterGoodsDonView.class);
+                    if (CollUtil.isNotEmpty(list)) {
+                        return GatewayResponse.SUCCESS.newBuilder().toResult(list);
+                    }
+                } catch (Exception e) {
+                }
+            }
+            String lockKey = registerCacheKey + ":lock";
+            if (!redisService.setNx(lockKey, "1", 10L)) {
+                return GatewayResponse.SUCCESS.newBuilder().toResult(Collections.emptyList());
+            }
             try {
-                List<RegisterGoodsDonView> list = Jsons.parseList(value, RegisterGoodsDonView.class);
-                if (CollUtil.isNotEmpty(list)) {
-                    return GatewayResponse.SUCCESS.newBuilder().toResult(list);
+                value = redisService.get(registerCacheKey);
+                if (value != null) {
+                    List<RegisterGoodsDonView> list = Jsons.parseList(value, RegisterGoodsDonView.class);
+                    if (CollUtil.isNotEmpty(list)) {
+                        return GatewayResponse.SUCCESS.newBuilder().toResult(list);
+                    }
                 }
-            } catch (Exception e) {
+                MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
+                List<RegisterGoodsDonView> dataList = beanSearcher.searchAll(RegisterGoodsDonView.class, builder.build());
+                DateTime now = DateTime.now();
+                dataList.forEach(data -> {
+                    Integer sold = registerOrderDonMapper.selectCount(Wrappers.lambdaQuery(RegisterOrderDon.class)
+                            .eq(RegisterOrderDon::getGoodsId, data.getId()).notIn(RegisterOrderDon::getStatus, Constant.noOrderStatus));
+                    data.setSold(sold + data.getVirtualSold());
+                    data.setNotifyMsg(getPayMsgTime(data.getId(), now, 2, null));
+                });
+                redisService.set(registerCacheKey, dataList, RedisService.key.REGISTER_HOME_PAGE_CACHE.getTimeout());
+                return GatewayResponse.SUCCESS.newBuilder().toResult(dataList);
+            } finally {
+                redisService.del(lockKey);
             }
+        } catch (Exception e) {
+            // Redis异常,返回空列表保护数据库
+            return GatewayResponse.SUCCESS.newBuilder().toResult(Collections.emptyList());
         }
-        MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
-        List<RegisterGoodsDonView> dataList = beanSearcher.searchAll(RegisterGoodsDonView.class, builder.build());
-        DateTime now = DateTime.now();
-        dataList.forEach(data -> {
-            Integer sold = registerOrderDonMapper.selectCount(Wrappers.lambdaQuery(RegisterOrderDon.class)
-                    .eq(RegisterOrderDon::getGoodsId, data.getId()).notIn(RegisterOrderDon::getStatus, Constant.noOrderStatus));
-            data.setSold(sold + data.getVirtualSold());
-            data.setNotifyMsg(getPayMsgTime(data.getId(), now, 2, null));
-        });
-        redisService.setNx(registerCacheKey, dataList, RedisService.key.REGISTER_HOME_PAGE_CACHE.getTimeout());
-        return GatewayResponse.SUCCESS.newBuilder().toResult(dataList);
     }
 
 
@@ -385,53 +405,65 @@ public class GoodsDonController {
 	 */
 	@GetMapping("/get/{id}")
 	public Result<? extends Object> getDetail(@PathVariable Long id, String customId, String dsCode, BigDecimal discount) {
-		if (StrUtil.isNotBlank(customId) && id != 15) {
-			Result<YhShopGoodsFrontView> yhShopGoodsDetail = getGoodsDetailByYhsId(yhShopFrontService.getYhsIdByCustomId(customId), id);
-			return yhShopGoodsDetail;
-		}
-		String goodsDetailKey = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "goods_detail:" + id;
-		//List<Long> filter_goodsIds = getFilterGoodsIds();
-		List<Long> filter_goodsIds = null;
-		String lang = request.getHeader("lang");
-		AtomicBoolean language = new AtomicBoolean(false);
-		if (lang != null && !StrUtil.equals(UserPageLanguage.Language.zh_CN.name(), lang)) {
-			goodsDetailKey += ":" + lang;
-			language.set(true);
-		}
-		//存在过滤平台 商品详情不返回
-		if (CollUtil.isNotEmpty(filter_goodsIds) && filter_goodsIds.contains(id)) {
-			return GatewayResponse.SUCCESS.newBuilder().toResult();
-		}
-		Object o = redisService.get(goodsDetailKey);
-		if (o == null) {
-			GoodsFrontListView views = beanSearcher.searchFirst(GoodsFrontListView.class, MapUtils.builder().field(GoodsFrontListView::getId, id)
-					.build());
-			if (views == null) {
-				return GatewayResponse.SUCCESS.newBuilder().toResult();
+		try {
+			if (StrUtil.isNotBlank(customId) && id != 15) {
+				Result<YhShopGoodsFrontView> yhShopGoodsDetail = getGoodsDetailByYhsId(yhShopFrontService.getYhsIdByCustomId(customId), id);
+				return yhShopGoodsDetail;
 			}
-
-			views.setSpecs(beanSearcher.searchFirst(GoodsDonSpecFrontView.class, MapUtils.builder().field(GoodsDonSpecFrontView::getGoodsId, views.getId()).build()));
-			MapBuilder builder = MapUtils.builder().field(GoodsDonSkuFrontView::getGoodsId, views.getId()).field(GoodsDonSkuFrontView::getStatus, true);
-
-			if (views.getType() == 1) {
-				builder.orderBy(GoodsDonSkuFrontView::getSorted).asc();
+			String goodsDetailKey = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "goods_detail:" + id;
+			List<Long> filter_goodsIds = null;
+			String lang = request.getHeader("lang");
+			AtomicBoolean language = new AtomicBoolean(false);
+			if (lang != null && !StrUtil.equals(UserPageLanguage.Language.zh_CN.name(), lang)) {
+				goodsDetailKey += ":" + lang;
+				language.set(true);
 			}
-			views.setSkuList(beanSearcher.searchAll(GoodsDonSkuFrontView.class, builder.build()));
-			views.setSold(getGoodsSold(views.getId(), views.getSold()));
-			//多语言
-			if (language.get()) {
-				backInfoTranslationsFrontService.setGoodsDetailLanguage(views, lang);
+			if (CollUtil.isNotEmpty(filter_goodsIds) && filter_goodsIds.contains(id)) {
+				return GatewayResponse.SUCCESS.newBuilder().toResult();
 			}
-			List<Long> gptBuyGids = getGptMirrorGiveawayBuyGids();
-			if (CollUtil.isNotEmpty(gptBuyGids) && gptBuyGids.contains(views.getId())) {
-				views.setIsGptGift(true);
+			Object o = redisService.get(goodsDetailKey);
+			if (o == null) {
+				// 加锁防止缓存击穿
+				String lockKey = goodsDetailKey + ":lock";
+				if (redisService.setNx(lockKey, "1", 10L)) {
+					try {
+						o = redisService.get(goodsDetailKey);
+						if (o == null) {
+							GoodsFrontListView views = beanSearcher.searchFirst(GoodsFrontListView.class, MapUtils.builder().field(GoodsFrontListView::getId, id)
+									.build());
+							if (views == null) {
+								return GatewayResponse.SUCCESS.newBuilder().toResult();
+							}
+
+							views.setSpecs(beanSearcher.searchFirst(GoodsDonSpecFrontView.class, MapUtils.builder().field(GoodsDonSpecFrontView::getGoodsId, views.getId()).build()));
+							MapBuilder builder = MapUtils.builder().field(GoodsDonSkuFrontView::getGoodsId, views.getId()).field(GoodsDonSkuFrontView::getStatus, true);
+
+							if (views.getType() == 1) {
+								builder.orderBy(GoodsDonSkuFrontView::getSorted).asc();
+							}
+							views.setSkuList(beanSearcher.searchAll(GoodsDonSkuFrontView.class, builder.build()));
+							views.setSold(getGoodsSold(views.getId(), views.getSold()));
+							if (language.get()) {
+								backInfoTranslationsFrontService.setGoodsDetailLanguage(views, lang);
+							}
+							List<Long> gptBuyGids = getGptMirrorGiveawayBuyGids();
+							if (CollUtil.isNotEmpty(gptBuyGids) && gptBuyGids.contains(views.getId())) {
+								views.setIsGptGift(true);
+							}
+							List<GoodsDonQaFrontView> donQaFrontViews = beanSearcher.searchAll(GoodsDonQaFrontView.class, MapUtils.builder().field(GoodsDonQaFrontView::getGoodsId, id).field(GoodsDonQaFrontView::getType, 1).build());
+							views.setQuestions(donQaFrontViews);
+							redisService.set(goodsDetailKey, views, RedisService.key.YH_HOME_PAGHE_CACHE.getTimeout() + 60 * RandomUtil.randomInt(10));
+							o = views;
+						}
+					} finally {
+						redisService.del(lockKey);
+					}
+				} else {
+					// 未获取锁,返回空
+					return GatewayResponse.SUCCESS.newBuilder().toResult();
+				}
 			}
-			List<GoodsDonQaFrontView> donQaFrontViews = beanSearcher.searchAll(GoodsDonQaFrontView.class, MapUtils.builder().field(GoodsDonQaFrontView::getGoodsId, id).field(GoodsDonQaFrontView::getType, 1).build());
-			views.setQuestions(donQaFrontViews);
-			redisService.setNx(goodsDetailKey, views, RedisService.key.YH_HOME_PAGHE_CACHE.getTimeout() + 60 * RandomUtil.randomInt(10));
-			o = redisService.get(goodsDetailKey);
-		}
-		Long fUid = StpUserUtil.getUserIdAfterLogin();
+			Long fUid = StpUserUtil.getUserIdAfterLogin();
 		GoodsFrontListView views = Jsons.parseObject(o, GoodsFrontListView.class);
 		AtomicLong dsUserId = new AtomicLong();
 		AtomicBoolean existsChannel = new AtomicBoolean(true);
@@ -522,73 +554,95 @@ public class GoodsDonController {
 			return true;
 		}).collect(Collectors.toList()));
 		return GatewayResponse.SUCCESS.newBuilder().toResult(views);
+		} catch (Exception e) {
+			// Redis异常,返回空保护数据库
+			return GatewayResponse.SUCCESS.newBuilder().toResult();
+		}
 	}
 	/**
      * 获取商品推荐平台
      */
     @GetMapping("/get/recommend/{id}")
     public Result<List<GoodsFrontListView>> getRecommendGoodsByGid(@PathVariable Long id, String customId, String dsCode) throws Exception {
-	    String key = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "recommend:" + id;
-	    Long yhsId = null;
-	    if (StrUtil.isNotBlank(customId)) {
-		    yhsId = yhShopFrontService.getYhsIdByCustomId(customId);
-		    key = RedisService.key.YH_HOME_PAGHE_CACHE_SHOP.getName() + yhsId + ":recommend:" + id;
-	    }
-	    Object o = redisService.get(key);
-	    Long fUid = StpUserUtil.getUserIdAfterLogin();
-	    List<GoodsFrontListView> goodsRecommendViews = null;
-	    if (o == null) {
-		    GoodsDon goodsDon = beanSearcher.searchFirst(GoodsDon.class, MapUtils.builder()
-				    .field(GoodsDon::getId, id).field(GoodsDon::getStatus, true)
-				    .field(GoodsDon::getDeleted, true)
-				    .build());
-		    if (goodsDon != null && StrUtil.isNotEmpty(goodsDon.getRecommendGoods())) {
-			    List<Long> recommend_gidList = Jsons.parseList(goodsDon.getRecommendGoods(), Long.class);
-			    MapBuilder mapBuilder = MapUtils.builder();
-			    if (yhsId != null) {
-				    mapBuilder.put("condition", String.format(" and g.id in (select distinct goods_id from yh_shop_goods_sku where yhs_id = %s and status is true and deleted is true) and g.is_distribute is true", yhsId));
-			    }
-			    mapBuilder.field(GoodsFrontListView::getId, recommend_gidList).op(Operator.InList);
-			    goodsRecommendViews = beanSearcher.searchAll(GoodsFrontListView.class, mapBuilder.build());
-			    redisService.setNx(key, Jsons.toJson(goodsRecommendViews), 60 * 15l);
-			    o = redisService.get(key);
-		    } else {
-			    return GatewayResponse.SUCCESS.newBuilder().toResult();
+	    try {
+		    String key = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "recommend:" + id;
+		    Long yhsId = null;
+		    if (StrUtil.isNotBlank(customId)) {
+			    yhsId = yhShopFrontService.getYhsIdByCustomId(customId);
+			    key = RedisService.key.YH_HOME_PAGHE_CACHE_SHOP.getName() + yhsId + ":recommend:" + id;
 		    }
-	    }
-	    if (goodsRecommendViews == null) {
-		    goodsRecommendViews = Jsons.parseList(o.toString(), GoodsFrontListView.class);
-	    }
-	    AtomicLong dsUserId = new AtomicLong();
-	    AtomicBoolean existsChannel = new AtomicBoolean(true);
-	    if (StrUtil.isNotBlank(dsCode)) {
-		    UserSharedDto userSharedDto = userService.getUserShredDtoByDsCode(dsCode);
-		    dsUserId.set(userSharedDto.getSharedId());
-	    }
-	    goodsRecommendViews = goodsRecommendViews.stream().filter(data -> {
-		    if (data.getIsOwns()) {
-			    if (dsUserId.get() == 0 && fUid != null && existsChannel.get()) {
-				    Long sharedId = userService.getSharedIdByUserId(fUid);
-				    if (sharedId == 0) {
-					    existsChannel.set(false);
+		    Object o = redisService.get(key);
+		    Long fUid = StpUserUtil.getUserIdAfterLogin();
+		    List<GoodsFrontListView> goodsRecommendViews = null;
+		    if (o == null) {
+			    // 加锁防止缓存击穿
+			    String lockKey = key + ":lock";
+			    if (redisService.setNx(lockKey, "1", 10L)) {
+				    try {
+					    o = redisService.get(key);
+					    if (o == null) {
+						    GoodsDon goodsDon = beanSearcher.searchFirst(GoodsDon.class, MapUtils.builder()
+								    .field(GoodsDon::getId, id).field(GoodsDon::getStatus, true)
+								    .field(GoodsDon::getDeleted, true)
+								    .build());
+						    if (goodsDon != null && StrUtil.isNotEmpty(goodsDon.getRecommendGoods())) {
+							    List<Long> recommend_gidList = Jsons.parseList(goodsDon.getRecommendGoods(), Long.class);
+							    MapBuilder mapBuilder = MapUtils.builder();
+							    Long finalYhsId = yhsId;
+							    if (yhsId != null) {
+								    mapBuilder.put("condition", String.format(" and g.id in (select distinct goods_id from yh_shop_goods_sku where yhs_id = %s and status is true and deleted is true) and g.is_distribute is true", finalYhsId));
+							    }
+							    mapBuilder.field(GoodsFrontListView::getId, recommend_gidList).op(Operator.InList);
+							    goodsRecommendViews = beanSearcher.searchAll(GoodsFrontListView.class, mapBuilder.build());
+							    redisService.set(key, Jsons.toJson(goodsRecommendViews), 60 * 15L);
+							    o = Jsons.toJson(goodsRecommendViews);
+						    } else {
+							    return GatewayResponse.SUCCESS.newBuilder().toResult();
+						    }
+					    }
+				    } finally {
+					    redisService.del(lockKey);
 				    }
-				    dsUserId.set(sharedId);
-			    }
-			    GoodsDonSku minPriceUserOwnsSku = goodsDonSkuMapper.checkAndReturnMinPriceUserOwnsSku(data.getId(), dsUserId.get());
-			    if (minPriceUserOwnsSku == null) {
-				    return false;
+			    } else {
+				    // 未获取锁,返回空
+				    return GatewayResponse.SUCCESS.newBuilder().toResult();
 			    }
-			    data.setPrice(minPriceUserOwnsSku.getPrice());
-			    data.setMonths(minPriceUserOwnsSku.getMonths());
-			    data.setDays(minPriceUserOwnsSku.getDays());
 		    }
-			//销量
-		    data.setSold(getGoodsSold(data.getId(), data.getSold()));
-		    //设置特定价格
-		    setSpecificPrice(data, fUid, dsUserId.get());
-		    return true;
-	    }).collect(Collectors.toList());
-	    return GatewayResponse.SUCCESS.newBuilder().toResult(goodsRecommendViews);
+		    if (goodsRecommendViews == null) {
+			    goodsRecommendViews = Jsons.parseList(o.toString(), GoodsFrontListView.class);
+		    }
+		    AtomicLong dsUserId = new AtomicLong();
+		    AtomicBoolean existsChannel = new AtomicBoolean(true);
+		    if (StrUtil.isNotBlank(dsCode)) {
+			    UserSharedDto userSharedDto = userService.getUserShredDtoByDsCode(dsCode);
+			    dsUserId.set(userSharedDto.getSharedId());
+		    }
+		    goodsRecommendViews = goodsRecommendViews.stream().filter(data -> {
+			    if (data.getIsOwns()) {
+				    if (dsUserId.get() == 0 && fUid != null && existsChannel.get()) {
+					    Long sharedId = userService.getSharedIdByUserId(fUid);
+					    if (sharedId == 0) {
+						    existsChannel.set(false);
+					    }
+					    dsUserId.set(sharedId);
+				    }
+				    GoodsDonSku minPriceUserOwnsSku = goodsDonSkuMapper.checkAndReturnMinPriceUserOwnsSku(data.getId(), dsUserId.get());
+				    if (minPriceUserOwnsSku == null) {
+					    return false;
+				    }
+				    data.setPrice(minPriceUserOwnsSku.getPrice());
+				    data.setMonths(minPriceUserOwnsSku.getMonths());
+				    data.setDays(minPriceUserOwnsSku.getDays());
+			    }
+			    data.setSold(getGoodsSold(data.getId(), data.getSold()));
+			    setSpecificPrice(data, fUid, dsUserId.get());
+			    return true;
+		    }).collect(Collectors.toList());
+		    return GatewayResponse.SUCCESS.newBuilder().toResult(goodsRecommendViews);
+	    } catch (Exception e) {
+		    // Redis异常,返回空保护数据库
+		    return GatewayResponse.SUCCESS.newBuilder().toResult();
+	    }
     }
 
     /**
@@ -609,12 +663,35 @@ public class GoodsDonController {
      * 获取评价列表
      */
     @GetMapping("/get/comments")
-    public Result<SearchResult<OrderCommentFrontView>> getComments() {
-        SearchResult<OrderCommentFrontView> search = beanSearcher.search(OrderCommentFrontView.class, MapUtils.flatBuilder(request.getParameterMap())
-                .orderBy(OrderCommentFrontView::getCommentTime).desc()
-                .orderBy(OrderCommentFrontView::getId).desc()
-                .build());
-        return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+    public Result<SearchResult<OrderCommentFrontView>> getComments(Long goodsId, @RequestParam(defaultValue = "0") Integer page, @RequestParam(defaultValue = "10") Integer size) {
+        try {
+            String cacheKey = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "comments:" + goodsId + ":" + page + ":" + size;
+            Object o = redisService.get(cacheKey);
+            if (o != null) {
+                return GatewayResponse.SUCCESS.newBuilder().toResult((SearchResult<OrderCommentFrontView>) o);
+            }
+            String lockKey = cacheKey + ":lock";
+            if (redisService.setNx(lockKey, "1", 10L)) {
+                try {
+                    o = redisService.get(cacheKey);
+                    if (o != null) {
+                        return GatewayResponse.SUCCESS.newBuilder().toResult((SearchResult<OrderCommentFrontView>) o);
+                    }
+                    SearchResult<OrderCommentFrontView> search = beanSearcher.search(OrderCommentFrontView.class, MapUtils.flatBuilder(request.getParameterMap())
+                            .orderBy(OrderCommentFrontView::getCommentTime).desc()
+                            .orderBy(OrderCommentFrontView::getId).desc()
+                            .build());
+                    redisService.set(cacheKey, search, 60 * 30L);
+                    return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+                } finally {
+                    redisService.del(lockKey);
+                }
+            } else {
+                return GatewayResponse.SUCCESS.newBuilder().toResult(new SearchResult<OrderCommentFrontView>());
+            }
+        } catch (Exception e) {
+            return GatewayResponse.SUCCESS.newBuilder().toResult(new SearchResult<OrderCommentFrontView>());
+        }
     }
 
     /**
@@ -632,82 +709,93 @@ public class GoodsDonController {
 	 */
 	@GetMapping("/get/homeManage")
 	public Result<Map<String, List<HomeManagementFrontView>>> getHomeManagementFrontPage(String customId, String dsCode, BigDecimal discount, Boolean isFilter) {
-		String key = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "homeManage";
-		Long yhsId = null;
-		if (StrUtil.isNotBlank(customId)) {
-			yhsId = yhShopFrontService.getYhsIdByCustomId(customId);
-			key = RedisService.key.YH_HOME_PAGHE_CACHE_SHOP.getName() + yhsId + ":homeManage";
-		}
-		Long fUid = StpUserUtil.getUserIdAfterLogin();
-		Boolean isFilterGoodsIds = isFilterGoodsIds(fUid, isFilter);
-		AtomicBoolean isRemoveRg = new AtomicBoolean(false);
-		if (isFilterGoodsIds) {
-			key += ":filter-ip";
-//			isRemoveRg.set(true);
-		}
-		String lang = request.getHeader("lang");
-		AtomicBoolean language = new AtomicBoolean(false);
-		if (lang != null && !StrUtil.equals(UserPageLanguage.Language.zh_CN.name(), lang)) {
-			key += ":" + lang;
-			language.set(true);
-		}
-		Object o = redisService.get(key);
-		if (o == null) {
-			try {
-                String condition = "g.deleted is true and g.status is true";
-                if (yhsId != null) {
-                    condition += String.format(" and g.id in (select distinct goods_id from yh_shop_goods_sku where yhs_id = %s and status is true and deleted is true) and g.is_distribute is true", yhsId);
-                }
-                Map<String, List<HomeManagementFrontView>> map = new ConcurrentHashMap<>();
-                final String conditionSql = condition;
-                Stream.of(HomeManagementConfig.Type.values())
-                        .forEach(type -> {
-                            if (isRemoveRg.get() && type == HomeManagementConfig.Type.rg) {
-                                return;
-                            }
-                            MapBuilder builder = MapUtils.builder()
-                                    .field(HomeManagementFrontView::getType, type.name());
-                            if (type == HomeManagementConfig.Type.ex || type == HomeManagementConfig.Type.vg) {
-                                builder.put("condition", conditionSql);
-                                if (isFilterGoodsIds) {
-                                    builder.field(HomeManagementFrontView::getFilter, Boolean.FALSE);
-                                }
-                            }
-                            List<HomeManagementFrontView> homeManagementFrontViews = beanSearcher.searchAll(HomeManagementFrontView.class, builder.build());
-                            //实物推荐多语言
-                            if (language.get() && type == HomeManagementConfig.Type.rg) {
-                                backInfoTranslationsFrontService.getHomeConfigRealGoodsLanguage(homeManagementFrontViews, lang);
-                            }
-                            map.putIfAbsent(type.name(), homeManagementFrontViews);
-                        });
-                redisService.setNx(key, map, 60 * 60l * 24 * 7);
-                o = redisService.get(key);
-            }catch (Exception e) {
-                //如果出现异常,先缓存空map
-                redisService.setNx(key, new ConcurrentHashMap<>(), 10L);
-                o = redisService.get(key);
-            }
-		}
-		AtomicLong dsUserId = new AtomicLong();
-		AtomicBoolean existsChannel = new AtomicBoolean(true);
-		if (StrUtil.isNotBlank(dsCode)) {
-			UserSharedDto userSharedDto = userService.getUserShredDtoByDsCode(dsCode);
-			dsUserId.set(userSharedDto.getSharedId());
-		}
-		Map<String, List<HomeManagementFrontView>> map = Jsons.parseObject(o, Map.class);
-		if (map.containsKey(HomeManagementConfig.Type.ex.name()) || map.containsKey(HomeManagementConfig.Type.vg.name())) {
-			try {
-				//精彩推荐
-				List<HomeManagementFrontView> exList = Jsons.parseList(Jsons.toJson(map.get(HomeManagementConfig.Type.ex.name())), HomeManagementFrontView.class);
-				setHomeConfigGoods(map, HomeManagementConfig.Type.ex, exList, dsUserId, existsChannel, fUid, discount);
-
-				//虚拟平台
-				List<HomeManagementFrontView> vgList = Jsons.parseList(Jsons.toJson(map.get(HomeManagementConfig.Type.vg.name())), HomeManagementFrontView.class);
-				setHomeConfigGoods(map, HomeManagementConfig.Type.vg, vgList, dsUserId, existsChannel, fUid, discount);
-			} catch (Exception e) {
+		try {
+			String key = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "homeManage";
+			Long yhsId = null;
+			if (StrUtil.isNotBlank(customId)) {
+				yhsId = yhShopFrontService.getYhsIdByCustomId(customId);
+				key = RedisService.key.YH_HOME_PAGHE_CACHE_SHOP.getName() + yhsId + ":homeManage";
+			}
+			Long fUid = StpUserUtil.getUserIdAfterLogin();
+			Boolean isFilterGoodsIds = isFilterGoodsIds(fUid, isFilter);
+			AtomicBoolean isRemoveRg = new AtomicBoolean(false);
+			if (isFilterGoodsIds) {
+				key += ":filter-ip";
+			}
+			String lang = request.getHeader("lang");
+			AtomicBoolean language = new AtomicBoolean(false);
+			if (lang != null && !StrUtil.equals(UserPageLanguage.Language.zh_CN.name(), lang)) {
+				key += ":" + lang;
+				language.set(true);
+			}
+			Object o = redisService.get(key);
+			if (o == null) {
+				// 加锁防止缓存击穿
+				String lockKey = key + ":lock";
+				if (redisService.setNx(lockKey, "1", 10L)) {
+					try {
+						o = redisService.get(key);
+						if (o == null) {
+							String condition = "g.deleted is true and g.status is true";
+							Long finalYhsId = yhsId;
+							if (yhsId != null) {
+								condition += String.format(" and g.id in (select distinct goods_id from yh_shop_goods_sku where yhs_id = %s and status is true and deleted is true) and g.is_distribute is true", yhsId);
+							}
+							Map<String, List<HomeManagementFrontView>> map = new ConcurrentHashMap<>();
+							final String conditionSql = condition;
+							Stream.of(HomeManagementConfig.Type.values())
+									.forEach(type -> {
+										if (isRemoveRg.get() && type == HomeManagementConfig.Type.rg) {
+											return;
+										}
+										MapBuilder builder = MapUtils.builder()
+												.field(HomeManagementFrontView::getType, type.name());
+										if (type == HomeManagementConfig.Type.ex || type == HomeManagementConfig.Type.vg) {
+											builder.put("condition", conditionSql);
+											if (isFilterGoodsIds) {
+												builder.field(HomeManagementFrontView::getFilter, Boolean.FALSE);
+											}
+										}
+										List<HomeManagementFrontView> homeManagementFrontViews = beanSearcher.searchAll(HomeManagementFrontView.class, builder.build());
+										if (language.get() && type == HomeManagementConfig.Type.rg) {
+											backInfoTranslationsFrontService.getHomeConfigRealGoodsLanguage(homeManagementFrontViews, lang);
+										}
+										map.putIfAbsent(type.name(), homeManagementFrontViews);
+									});
+							redisService.set(key, map, 60 * 60L * 24 * 7);
+							o = map;
+						}
+					} finally {
+						redisService.del(lockKey);
+					}
+				} else {
+					// 未获取锁,返回空map
+					Map<String, List<HomeManagementFrontView>> emptyMap = new ConcurrentHashMap<>();
+					return GatewayResponse.SUCCESS.newBuilder().toResult(emptyMap);
+				}
 			}
+			AtomicLong dsUserId = new AtomicLong();
+			AtomicBoolean existsChannel = new AtomicBoolean(true);
+			if (StrUtil.isNotBlank(dsCode)) {
+				UserSharedDto userSharedDto = userService.getUserShredDtoByDsCode(dsCode);
+				dsUserId.set(userSharedDto.getSharedId());
+			}
+			Map<String, List<HomeManagementFrontView>> map = Jsons.parseObject(o, Map.class);
+			if (map.containsKey(HomeManagementConfig.Type.ex.name()) || map.containsKey(HomeManagementConfig.Type.vg.name())) {
+				try {
+					List<HomeManagementFrontView> exList = Jsons.parseList(Jsons.toJson(map.get(HomeManagementConfig.Type.ex.name())), HomeManagementFrontView.class);
+					setHomeConfigGoods(map, HomeManagementConfig.Type.ex, exList, dsUserId, existsChannel, fUid, discount);
+					List<HomeManagementFrontView> vgList = Jsons.parseList(Jsons.toJson(map.get(HomeManagementConfig.Type.vg.name())), HomeManagementFrontView.class);
+					setHomeConfigGoods(map, HomeManagementConfig.Type.vg, vgList, dsUserId, existsChannel, fUid, discount);
+				} catch (Exception e) {
+				}
+			}
+			return GatewayResponse.SUCCESS.newBuilder().toResult(map);
+		} catch (Exception e) {
+			// Redis异常,返回空map保护数据库
+			Map<String, List<HomeManagementFrontView>> emptyMap = new ConcurrentHashMap<>();
+			return GatewayResponse.SUCCESS.newBuilder().toResult(emptyMap);
 		}
-		return GatewayResponse.SUCCESS.newBuilder().toResult(map);
 	}
 
 	/**
@@ -1040,40 +1128,65 @@ public class GoodsDonController {
      */
     @GetMapping("/get/shop/goods/{yhsId}")
     public Result<List<YhShopGoodsFrontView>> getShopGoods(@PathVariable Long yhsId) {
-        String yhShopCacheKey = RedisService.key.YH_HOME_PAGHE_CACHE_SHOP.getName() + yhsId;
-        Object value = redisService.get(yhShopCacheKey);
-        List<YhShopGoodsFrontView> list = null;
-        if (value != null) {
-            try {
-                list = Jsons.parseList(value, YhShopGoodsFrontView.class);
-            } catch (Exception e) {
+        try {
+            String yhShopCacheKey = RedisService.key.YH_HOME_PAGHE_CACHE_SHOP.getName() + yhsId;
+            Object value = redisService.get(yhShopCacheKey);
+            List<YhShopGoodsFrontView> list = null;
+            if (value != null) {
+                try {
+                    list = Jsons.parseList(value, YhShopGoodsFrontView.class);
+                } catch (Exception e) {
+                }
             }
+            if (CollUtil.isEmpty(list)) {
+                // 加锁防止缓存击穿
+                String lockKey = yhShopCacheKey + ":lock";
+                if (redisService.setNx(lockKey, "1", 10L)) {
+                    try {
+                        value = redisService.get(yhShopCacheKey);
+                        if (value != null) {
+                            try {
+                                list = Jsons.parseList(value, YhShopGoodsFrontView.class);
+                            } catch (Exception e) {
+                            }
+                        }
+                        if (CollUtil.isEmpty(list)) {
+                            MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
+                            builder.put("condition", String.format("and yhs_id = %s", yhsId));
+                            list = beanSearcher.searchAll(YhShopGoodsFrontView.class, builder.build());
+                            redisService.set(yhShopCacheKey, list, RedisService.key.YH_HOME_PAGHE_CACHE_SHOP.getTimeout());
+                        }
+                    } finally {
+                        redisService.del(lockKey);
+                    }
+                } else {
+                    // 未获取锁,返回空列表
+                    return GatewayResponse.SUCCESS.newBuilder().toResult(Collections.emptyList());
+                }
+            }
+            DateTime now = DateTime.now();
+            list.forEach(data -> {
+                data.setSold(getGoodsSold(data.getId(), data.getSold()));
+                data.setNotifyMsg(getPayMsgTime(data.getId(), now, 1, yhsId));
+                Optional.ofNullable(yhShopGoodsSkuMapper.selectOne(Wrappers.lambdaQuery(YhShopGoodsSku.class)
+                        .eq(YhShopGoodsSku::getYhsId, yhsId)
+                        .eq(YhShopGoodsSku::getGoodsId, data.getId())
+                        .eq(YhShopGoodsSku::getPrice, data.getPrice())
+                        .eq(YhShopGoodsSku::getStatus, 1)
+                        .eq(YhShopGoodsSku::getDeleted, 1)
+                        .last("limit 1"))).ifPresent(yhSku -> {
+                    GoodsDonSku sku = goodsDonSkuMapper.selectById(yhSku.getSkuId());
+                    if (sku != null) {
+                        data.setMonths(sku.getMonths());
+                        data.setDays(sku.getDays());
+                    }
+                });
+            });
+            return GatewayResponse.SUCCESS.newBuilder().toResult(list);
+        } catch (Exception e) {
+            // Redis异常,返回空列表保护数据库
+            return GatewayResponse.SUCCESS.newBuilder().toResult(Collections.emptyList());
         }
-        if (CollUtil.isEmpty(list)) {
-            MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
-            builder.put("condition", String.format("and yhs_id = %s", yhsId));
-            list = beanSearcher.searchAll(YhShopGoodsFrontView.class, builder.build());
-            redisService.setNx(yhShopCacheKey, list, RedisService.key.YH_HOME_PAGHE_CACHE_SHOP.getTimeout());
-        }
-        DateTime now = DateTime.now();
-	    list.forEach(data -> {
-		    data.setSold(getGoodsSold(data.getId(), data.getSold()));
-		    data.setNotifyMsg(getPayMsgTime(data.getId(), now, 1, yhsId));
-		    Optional.ofNullable(yhShopGoodsSkuMapper.selectOne(Wrappers.lambdaQuery(YhShopGoodsSku.class)
-				    .eq(YhShopGoodsSku::getYhsId, yhsId)
-				    .eq(YhShopGoodsSku::getGoodsId, data.getId())
-				    .eq(YhShopGoodsSku::getPrice, data.getPrice())
-				    .eq(YhShopGoodsSku::getStatus, 1)
-				    .eq(YhShopGoodsSku::getDeleted, 1)
-				    .last("limit 1"))).ifPresent(yhSku -> {
-			    GoodsDonSku sku = goodsDonSkuMapper.selectById(yhSku.getSkuId());
-			    if (sku != null) {
-				    data.setMonths(sku.getMonths());
-				    data.setDays(sku.getDays());
-			    }
-		    });
-	    });
-	    return GatewayResponse.SUCCESS.newBuilder().toResult(list);
     }
 
     /**
@@ -1111,108 +1224,117 @@ public class GoodsDonController {
 	 */
 	@GetMapping("/get/categoryGoods")
 	public Result<? extends Object> getGoodsByCategory(Long cgy, String customId, String dsCode, BigDecimal discount, Boolean isFilter) {
-		if (StrUtil.isNotBlank(customId)) {
-			Result<List<YhShopGoodsFrontCategoryView>> shopGoods = getShopCategoryGoods(yhShopFrontService.getYhsIdByCustomId(customId), cgy);
-			return shopGoods;
-		}
-		Long fUid = StpUserUtil.getUserIdAfterLogin();
-		String categoryGoodsKey = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "category:goods";
-		if (cgy != null) {
-			categoryGoodsKey += ":" + cgy;
-		}
-		Boolean isFilterGoodsIds = isFilterGoodsIds(fUid, isFilter);
-		if (isFilterGoodsIds) {
-			categoryGoodsKey += ":filter-ip";
-		}
-		String lang = request.getHeader("lang");
-		AtomicBoolean language = new AtomicBoolean(false);
-		if (lang != null && UserPageLanguage.Language.en_US.name().equals(lang)) {
-			categoryGoodsKey += ":" + lang;
-			language.set(true);
-		}
-		Object o = redisService.get(categoryGoodsKey);
-		if (o == null) {
-			DateTime now = DateTime.now();
-			MapBuilder mapBuilder = MapUtils.flatBuilder(request.getParameterMap());
+		try {
+			if (StrUtil.isNotBlank(customId)) {
+				Result<List<YhShopGoodsFrontCategoryView>> shopGoods = getShopCategoryGoods(yhShopFrontService.getYhsIdByCustomId(customId), cgy);
+				return shopGoods;
+			}
+			Long fUid = StpUserUtil.getUserIdAfterLogin();
+			String categoryGoodsKey = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "category:goods";
 			if (cgy != null) {
-				String condition = String.format(" and gcr.category = %s", cgy);
-				mapBuilder.put("condition", condition);
+				categoryGoodsKey += ":" + cgy;
 			}
+			Boolean isFilterGoodsIds = isFilterGoodsIds(fUid, isFilter);
 			if (isFilterGoodsIds) {
-				//特殊ip需要过滤的商品
-				mapBuilder.field(GoodsFrontListCategoryView::getFilter, Boolean.FALSE);
+				categoryGoodsKey += ":filter-ip";
 			}
-			List<GoodsFrontListCategoryView> goodsFrontListViews = beanSearcher.searchAll(GoodsFrontListCategoryView.class, mapBuilder.build());
-			List<Long> gptBuyGids = getGptMirrorGiveawayBuyGids();
-			goodsFrontListViews.forEach(data -> {
-				data.setSold(getGoodsSold(data.getId(), data.getSold()));
-				data.setNotifyMsg(getPayMsgTime(data.getId(), now, 1, null));
-				if (CollUtil.isNotEmpty(gptBuyGids) && gptBuyGids.contains(data.getId())) {
-					data.setIsGptGift(true);
+			String lang = request.getHeader("lang");
+			AtomicBoolean language = new AtomicBoolean(false);
+			if (lang != null && UserPageLanguage.Language.en_US.name().equals(lang)) {
+				categoryGoodsKey += ":" + lang;
+				language.set(true);
+			}
+			Object o = redisService.get(categoryGoodsKey);
+			if (o == null) {
+				// 加锁防止缓存击穿
+				String lockKey = categoryGoodsKey + ":lock";
+				if (redisService.setNx(lockKey, "1", 10L)) {
+					try {
+						o = redisService.get(categoryGoodsKey);
+						if (o == null) {
+							DateTime now = DateTime.now();
+							MapBuilder mapBuilder = MapUtils.flatBuilder(request.getParameterMap());
+							if (cgy != null) {
+								String condition = String.format(" and gcr.category = %s", cgy);
+								mapBuilder.put("condition", condition);
+							}
+							if (isFilterGoodsIds) {
+								mapBuilder.field(GoodsFrontListCategoryView::getFilter, Boolean.FALSE);
+							}
+							List<GoodsFrontListCategoryView> goodsFrontListViews = beanSearcher.searchAll(GoodsFrontListCategoryView.class, mapBuilder.build());
+							List<Long> gptBuyGids = getGptMirrorGiveawayBuyGids();
+							goodsFrontListViews.forEach(data -> {
+								data.setSold(getGoodsSold(data.getId(), data.getSold()));
+								data.setNotifyMsg(getPayMsgTime(data.getId(), now, 1, null));
+								if (CollUtil.isNotEmpty(gptBuyGids) && gptBuyGids.contains(data.getId())) {
+									data.setIsGptGift(true);
+								}
+								if (language.get()) {
+									backInfoTranslationsFrontService.setCategoryGoodsLanguage(data, lang);
+								}
+							});
+							redisService.set(categoryGoodsKey, goodsFrontListViews, RedisService.key.YH_HOME_PAGHE_CACHE.getTimeout() + 10 * 60);
+							o = goodsFrontListViews;
+						}
+					} finally {
+						redisService.del(lockKey);
+					}
+				} else {
+					// 未获取锁,返回空列表
+					return GatewayResponse.SUCCESS.newBuilder().toResult(Collections.emptyList());
 				}
-				if (language.get()) {
-					//多语言
-					backInfoTranslationsFrontService.setCategoryGoodsLanguage(data, lang);
+			}
+			List<GoodsFrontListCategoryView> goodsFrontListViews = Jsons.parseList(o, GoodsFrontListCategoryView.class);
+			AtomicLong dsUserId = new AtomicLong();
+			AtomicBoolean existsChannel = new AtomicBoolean(true);
+			if (StrUtil.isNotBlank(dsCode)) {
+				UserSharedDto userSharedDto = userService.getUserShredDtoByDsCode(dsCode);
+				dsUserId.set(userSharedDto.getSharedId());
+			}
+			AtomicBoolean filterCourseGoods = new AtomicBoolean(false);
+			if (fUid != null && cgy != null && (cgy == 3 || cgy == 4)) {
+				List<Long> userIdList = userBindRelationService.getRelationUserIdList(fUid, null);
+				Integer orders = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class)
+						.in(OrderDon::getUserId, userIdList)
+						.eq(OrderDon::getSkuId, 444)
+						.notIn(OrderDon::getStatus, Constant.noOrderStatus));
+				if (orders > 0) {
+					filterCourseGoods.set(true);
 				}
-			});
-			redisService.setNx(categoryGoodsKey, goodsFrontListViews, RedisService.key.YH_HOME_PAGHE_CACHE.getTimeout() + 10 * 60);
-			o = redisService.get(categoryGoodsKey);
-		}
-		List<GoodsFrontListCategoryView> goodsFrontListViews = Jsons.parseList(o, GoodsFrontListCategoryView.class);
-		AtomicLong dsUserId = new AtomicLong();
-		AtomicBoolean existsChannel = new AtomicBoolean(true);
-		if (StrUtil.isNotBlank(dsCode)) {
-			UserSharedDto userSharedDto = userService.getUserShredDtoByDsCode(dsCode);
-			dsUserId.set(userSharedDto.getSharedId());
-		}
-		AtomicBoolean filterCourseGoods = new AtomicBoolean(false);
-		//增值服务分类
-		if (fUid != null && cgy != null && (cgy == 3 || cgy == 4)) {
-			//GPT Plus基础2月 课程不展示
-			List<Long> userIdList = userBindRelationService.getRelationUserIdList(fUid, null);
-			Integer orders = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class)
-					.in(OrderDon::getUserId, userIdList)
-					.eq(OrderDon::getSkuId, 444)
-					.notIn(OrderDon::getStatus, Constant.noOrderStatus));
-			if (orders > 0) {
-				filterCourseGoods.set(true);
 			}
-		}
-		goodsFrontListViews = goodsFrontListViews.stream().filter(data -> {
-			if (data.getIsOwns()) {
-				if (dsUserId.get() == 0 && fUid != null && existsChannel.get()) {
-					Long sharedId = userService.getSharedIdByUserId(fUid);
-					if (sharedId == 0) {
-						existsChannel.set(false);
+			goodsFrontListViews = goodsFrontListViews.stream().filter(data -> {
+				if (data.getIsOwns()) {
+					if (dsUserId.get() == 0 && fUid != null && existsChannel.get()) {
+						Long sharedId = userService.getSharedIdByUserId(fUid);
+						if (sharedId == 0) {
+							existsChannel.set(false);
+						}
+						dsUserId.set(sharedId);
 					}
-					dsUserId.set(sharedId);
+					GoodsDonSku minPriceUserOwnsSku = goodsDonSkuMapper.checkAndReturnMinPriceUserOwnsSku(data.getId(), dsUserId.get());
+					if (minPriceUserOwnsSku == null) {
+						return false;
+					}
+					data.setPrice(minPriceUserOwnsSku.getPrice());
+					data.setMonths(minPriceUserOwnsSku.getMonths());
+					data.setDays(minPriceUserOwnsSku.getDays());
 				}
-				GoodsDonSku minPriceUserOwnsSku = goodsDonSkuMapper.checkAndReturnMinPriceUserOwnsSku(data.getId(), dsUserId.get());
-				if (minPriceUserOwnsSku == null) {
+				if (filterCourseGoods.get() && data.getSpecialType() != null && data.getSpecialType() == GoodsDon.SpecialType.courseware) {
 					return false;
 				}
-				data.setPrice(minPriceUserOwnsSku.getPrice());
-				data.setMonths(minPriceUserOwnsSku.getMonths());
-				data.setDays(minPriceUserOwnsSku.getDays());
-			}
-			//课件类型 且过滤
-			if (filterCourseGoods.get() && data.getSpecialType() != null && data.getSpecialType() == GoodsDon.SpecialType.courseware) {
-				return false;
-			}
-			//设置特定价格
-			setGcSpecificPrice(data, fUid, dsUserId.get());
-			//设置用户存在优惠券的优惠商品价格
-			data.setChannelDiscount(discount);
-			//商品优惠折扣
-			setUserCouponGoodsMoney(fUid, data);
-			//未登录
-			if (fUid == null) {
-				//推荐优惠券商品最低折扣
-				setGoodsCouponMoney(data);
-			}
-			return true;
-		}).collect(Collectors.toList());
-		return GatewayResponse.SUCCESS.newBuilder().toResult(goodsFrontListViews);
+				setGcSpecificPrice(data, fUid, dsUserId.get());
+				data.setChannelDiscount(discount);
+				setUserCouponGoodsMoney(fUid, data);
+				if (fUid == null) {
+					setGoodsCouponMoney(data);
+				}
+				return true;
+			}).collect(Collectors.toList());
+			return GatewayResponse.SUCCESS.newBuilder().toResult(goodsFrontListViews);
+		} catch (Exception e) {
+			// Redis异常,返回空列表保护数据库
+			return GatewayResponse.SUCCESS.newBuilder().toResult(Collections.emptyList());
+		}
 	}
 
 	@GetMapping("/get/shop/categoryGoods/{yhsId}")
@@ -1358,45 +1480,63 @@ public class GoodsDonController {
 	 */
 	@GetMapping("/get/subsidy")
 	public Result<List<GoodsDonSkuSubsidyFrontView>> getSubsidyGoods(Boolean isFilter) {
-		String key = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "subsidy";
-		Long fUid = StpUserUtil.getUserIdAfterLogin();
-		Boolean filterGoodsIds = isFilterGoodsIds(fUid, isFilter);
-		if (filterGoodsIds) {
-			key += ":filter-ip";
-		}
-		Object o = redisService.get(key);
-		if (o == null) {
-			MapBuilder builder = MapUtils.builder();
+		try {
+			String key = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "subsidy";
+			Long fUid = StpUserUtil.getUserIdAfterLogin();
+			Boolean filterGoodsIds = isFilterGoodsIds(fUid, isFilter);
 			if (filterGoodsIds) {
-				builder.field(GoodsDonSkuSubsidyFrontView::getFilter, Boolean.FALSE);
+				key += ":filter-ip";
 			}
-			List<GoodsDonSkuSubsidyFrontView> subsidyList = beanSearcher.searchAll(GoodsDonSkuSubsidyFrontView.class, builder.build());
-			subsidyList.forEach(e -> {
-				Optional.ofNullable(beanSearcher.searchFirst(GoodsDonSkuSubsidyDetailView.class, MapUtils.builder().field(GoodsDonSkuSubsidyDetailView::getGoodsId, e.getId()).field(GoodsDonSkuSubsidyDetailView::getPrice, e.getPrice()).build())).ifPresent(sku -> {
-					e.setOriPrice(sku.getOriPrice());
-					e.setMonths(sku.getMonths());
-					e.setDays(sku.getDays());
-					e.setSkuId(sku.getId());
-					e.setPicture(sku.getSubsidyPicture());
-				});
-			});
-			redisService.setNx(key, subsidyList, 60 * 60 * 24 * 7L);
-			o = redisService.get(key);
-		}
-		List<GoodsDonSkuSubsidyFrontView> subsidyList = Jsons.parseList(o, GoodsDonSkuSubsidyFrontView.class);
-		if (CollUtil.isEmpty(subsidyList)) {
-			return GatewayResponse.SUCCESS.newBuilder().toResult(subsidyList);
-		}
-		Long userId = StpUserUtil.getUserIdAfterLogin();
-		if (userId != null) {
-			List<Long> relationUserIdList = userBindRelationService.getRelationUserIdList(userId, null);
-			//过滤用户已经购买过平台
-			List<Long> goodsIds = orderDonMapper.getPayGoodsIds(relationUserIdList);
-			if (CollUtil.isNotEmpty(goodsIds)) {
-				subsidyList = subsidyList.stream().filter(data -> !goodsIds.contains(data.getId())).collect(Collectors.toList());
+			Object o = redisService.get(key);
+			if (o == null) {
+				// 加锁防止缓存击穿
+				String lockKey = key + ":lock";
+				if (redisService.setNx(lockKey, "1", 10L)) {
+					try {
+						o = redisService.get(key);
+						if (o == null) {
+							MapBuilder builder = MapUtils.builder();
+							if (filterGoodsIds) {
+								builder.field(GoodsDonSkuSubsidyFrontView::getFilter, Boolean.FALSE);
+							}
+							List<GoodsDonSkuSubsidyFrontView> subsidyList = beanSearcher.searchAll(GoodsDonSkuSubsidyFrontView.class, builder.build());
+							subsidyList.forEach(e -> {
+								Optional.ofNullable(beanSearcher.searchFirst(GoodsDonSkuSubsidyDetailView.class, MapUtils.builder().field(GoodsDonSkuSubsidyDetailView::getGoodsId, e.getId()).field(GoodsDonSkuSubsidyDetailView::getPrice, e.getPrice()).build())).ifPresent(sku -> {
+									e.setOriPrice(sku.getOriPrice());
+									e.setMonths(sku.getMonths());
+									e.setDays(sku.getDays());
+									e.setSkuId(sku.getId());
+									e.setPicture(sku.getSubsidyPicture());
+								});
+							});
+							redisService.set(key, subsidyList, 60 * 60 * 24 * 7L);
+							o = subsidyList;
+						}
+					} finally {
+						redisService.del(lockKey);
+					}
+				} else {
+					// 未获取锁,返回空列表
+					return GatewayResponse.SUCCESS.newBuilder().toResult(Collections.emptyList());
+				}
+			}
+			List<GoodsDonSkuSubsidyFrontView> subsidyList = Jsons.parseList(o, GoodsDonSkuSubsidyFrontView.class);
+			if (CollUtil.isEmpty(subsidyList)) {
+				return GatewayResponse.SUCCESS.newBuilder().toResult(subsidyList);
+			}
+			Long userId = StpUserUtil.getUserIdAfterLogin();
+			if (userId != null) {
+				List<Long> relationUserIdList = userBindRelationService.getRelationUserIdList(userId, null);
+				List<Long> goodsIds = orderDonMapper.getPayGoodsIds(relationUserIdList);
+				if (CollUtil.isNotEmpty(goodsIds)) {
+					subsidyList = subsidyList.stream().filter(data -> !goodsIds.contains(data.getId())).collect(Collectors.toList());
+				}
 			}
+			return GatewayResponse.SUCCESS.newBuilder().toResult(subsidyList);
+		} catch (Exception e) {
+			// Redis异常,返回空列表保护数据库
+			return GatewayResponse.SUCCESS.newBuilder().toResult(Collections.emptyList());
 		}
-		return GatewayResponse.SUCCESS.newBuilder().toResult(subsidyList);
 	}
 
 	/**
@@ -1518,14 +1658,32 @@ public class GoodsDonController {
 	 * @return
 	 */
 	private Integer getGoodsSold(Long goodsId, Integer virtualSold) {
-		Object soldObj = redisService.get(RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "sold:" + goodsId);
-		if (soldObj == null) {
-			Integer sold = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class)
-					.eq(OrderDon::getGoodsId, goodsId).notIn(OrderDon::getStatus, Constant.noOrderStatus));
-			soldObj = sold + virtualSold;
-			redisService.set(RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "sold:" + goodsId, soldObj, RedisService.key.YH_HOME_PAGHE_CACHE.getTimeout());
+		try {
+			String cacheKey = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "sold:" + goodsId;
+			Object soldObj = redisService.get(cacheKey);
+			if (soldObj == null) {
+				String lockKey = cacheKey + ":lock";
+				if (redisService.setNx(lockKey, "1", 10L)) {
+					try {
+						soldObj = redisService.get(cacheKey);
+						if (soldObj == null) {
+							Integer sold = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class)
+									.eq(OrderDon::getGoodsId, goodsId).notIn(OrderDon::getStatus, Constant.noOrderStatus));
+							soldObj = sold + virtualSold;
+							redisService.set(cacheKey, soldObj, RedisService.key.YH_HOME_PAGHE_CACHE.getTimeout());
+						}
+					} finally {
+						redisService.del(lockKey);
+					}
+				} else {
+					return virtualSold;
+				}
+			}
+			return Integer.parseInt(soldObj.toString());
+		} catch (Exception e) {
+			// Redis异常,返回虚拟销量保护数据库
+			return virtualSold;
 		}
-		return Integer.parseInt(soldObj.toString());
 	}
 
 	/**

+ 86 - 30
netflix-web/src/main/java/com/cyksj/web/controller/information/InformationController.java

@@ -47,16 +47,35 @@ public class InformationController {
      */
     @GetMapping("/get")
     public Result<IPage<InformationListView>> getInformation(Long categoryId, @RequestParam(defaultValue = "0") Integer start, @RequestParam(defaultValue = "5") Integer limit) {
-        String key = RedisService.key.INFORMATION_KEY.getName() + String.format(":list:%s:%s", start, limit);
-        if (categoryId != null) {
-            key += ":ct:" + categoryId;
-        }
-        IPage<InformationListView> information  = (IPage<InformationListView>) redisService.get(key);
-        if (information == null) {
-            information = informationService.getInformation(categoryId, start, limit);
-            redisService.setNx(key, information, 60L * 60 * 24 * 7);
+        try {
+            String key = RedisService.key.INFORMATION_KEY.getName() + String.format(":list:%s:%s", start, limit);
+            if (categoryId != null) {
+                key += ":ct:" + categoryId;
+            }
+            IPage<InformationListView> information = (IPage<InformationListView>) redisService.get(key);
+            if (information == null) {
+                // 加锁防止缓存击穿
+                String lockKey = key + ":lock";
+                if (redisService.setNx(lockKey, "1", 10L)) {
+                    try {
+                        information = (IPage<InformationListView>) redisService.get(key);
+                        if (information == null) {
+                            information = informationService.getInformation(categoryId, start, limit);
+                            redisService.set(key, information, 60L * 60 * 24 * 7);
+                        }
+                    } finally {
+                        redisService.del(lockKey);
+                    }
+                } else {
+                    // 未获取锁,返回空
+                    return GatewayResponse.SUCCESS.newBuilder().toResult();
+                }
+            }
+            return GatewayResponse.SUCCESS.newBuilder().toResult(information);
+        } catch (Exception e) {
+            // Redis异常,返回空保护数据库
+            return GatewayResponse.SUCCESS.newBuilder().toResult();
         }
-        return GatewayResponse.SUCCESS.newBuilder().toResult(information);
     }
 
 
@@ -65,16 +84,35 @@ public class InformationController {
      */
     @GetMapping("/get/category")
     public Result<List<InformationCategory>> getInformationCategory() {
-        String key = RedisService.key.INFORMATION_KEY.getName() + ":category";
-        List<InformationCategory> informationCategory = (List<InformationCategory>) redisService.get(key);
-        if (informationCategory == null) {
-            informationCategory = informationCategoryService.getInformationCategory();
-            if (CollUtil.isEmpty(informationCategory)) {
-                return GatewayResponse.SUCCESS.newBuilder().toResult();
+        try {
+            String key = RedisService.key.INFORMATION_KEY.getName() + ":category";
+            List<InformationCategory> informationCategory = (List<InformationCategory>) redisService.get(key);
+            if (informationCategory == null) {
+                // 加锁防止缓存击穿
+                String lockKey = key + ":lock";
+                if (redisService.setNx(lockKey, "1", 10L)) {
+                    try {
+                        informationCategory = (List<InformationCategory>) redisService.get(key);
+                        if (informationCategory == null) {
+                            informationCategory = informationCategoryService.getInformationCategory();
+                            if (CollUtil.isEmpty(informationCategory)) {
+                                return GatewayResponse.SUCCESS.newBuilder().toResult();
+                            }
+                            redisService.set(key, informationCategory, 60L * 60 * 24 * 7);
+                        }
+                    } finally {
+                        redisService.del(lockKey);
+                    }
+                } else {
+                    // 未获取锁,返回空
+                    return GatewayResponse.SUCCESS.newBuilder().toResult();
+                }
             }
-            redisService.setNx(key, informationCategory, 60L * 60 * 24 * 7);
+            return GatewayResponse.SUCCESS.newBuilder().toResult(informationCategory);
+        } catch (Exception e) {
+            // Redis异常,返回空保护数据库
+            return GatewayResponse.SUCCESS.newBuilder().toResult();
         }
-        return GatewayResponse.SUCCESS.newBuilder().toResult(informationCategory);
     }
 
     /**
@@ -82,20 +120,38 @@ public class InformationController {
      */
     @GetMapping("/get/detail/{id}")
     public Result<InformationDetailView> getInformation(@PathVariable Long id) {
-        String key = RedisService.key.INFORMATION_KEY.getName() + "id:" + id;
-        InformationDetailView view = (InformationDetailView) redisService.get(key);
-        if (view == null){
-            view = beanSearcher.searchFirst(InformationDetailView.class, MapUtils.flatBuilder(request.getParameterMap())
-                    .field(InformationDetailView::getId, id).build());
-            try {
-                List<Long> goodsIds = Jsons.parseList(view.getGoodsIds(), Long.class);
-                List<GoodsFrontListView> goodsList = beanSearcher.searchAll(GoodsFrontListView.class, MapUtils.flatBuilder(request.getParameterMap()).field(GoodsFrontListView::getId,goodsIds).op(Operator.InList).build());
-                view.setGoods(goodsList);
-            } catch (Exception e) {
-                e.printStackTrace();
+        try {
+            String key = RedisService.key.INFORMATION_KEY.getName() + "id:" + id;
+            InformationDetailView view = (InformationDetailView) redisService.get(key);
+            if (view == null) {
+                // 加锁防止缓存击穿
+                String lockKey = key + ":lock";
+                if (redisService.setNx(lockKey, "1", 10L)) {
+                    try {
+                        view = (InformationDetailView) redisService.get(key);
+                        if (view == null) {
+                            view = beanSearcher.searchFirst(InformationDetailView.class, MapUtils.flatBuilder(request.getParameterMap())
+                                    .field(InformationDetailView::getId, id).build());
+                            try {
+                                List<Long> goodsIds = Jsons.parseList(view.getGoodsIds(), Long.class);
+                                List<GoodsFrontListView> goodsList = beanSearcher.searchAll(GoodsFrontListView.class, MapUtils.flatBuilder(request.getParameterMap()).field(GoodsFrontListView::getId, goodsIds).op(Operator.InList).build());
+                                view.setGoods(goodsList);
+                            } catch (Exception ignored) {
+                            }
+                            redisService.set(key, view, RedisService.key.INFORMATION_KEY.getTimeout());
+                        }
+                    } finally {
+                        redisService.del(lockKey);
+                    }
+                } else {
+                    // 未获取锁,返回空
+                    return GatewayResponse.SUCCESS.newBuilder().toResult();
+                }
             }
-            redisService.setNx(key, view, RedisService.key.INFORMATION_KEY.getTimeout());
+            return GatewayResponse.SUCCESS.newBuilder().toResult(view);
+        } catch (Exception e) {
+            // Redis异常,返回空保护数据库
+            return GatewayResponse.SUCCESS.newBuilder().toResult();
         }
-        return GatewayResponse.SUCCESS.newBuilder().toResult(view);
     }
 }

+ 31 - 11
netflix-web/src/main/java/com/cyksj/web/controller/sys/SysConfigController.java

@@ -74,19 +74,39 @@ public class SysConfigController {
 
 	@GetMapping("/get")
 	public Result<SysConfig> get(String key) {
-		SysConfig sysConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, key).last(" limit 1"));
-
-		if (sysConfig == null) {
+		try {
+			String cacheKey = RedisService.key.SYS_CONFIG_CACHE_KEY.getName() + key;
+			Object o = redisService.get(cacheKey);
+			if (o != null) {
+				return GatewayResponse.SUCCESS.newBuilder().toResult((SysConfig) o);
+			}
+			// 加锁防止缓存击穿
+			String lockKey = cacheKey + ":lock";
+			if (redisService.setNx(lockKey, "1", 10L)) {
+				try {
+					o = redisService.get(cacheKey);
+					if (o != null) {
+						return GatewayResponse.SUCCESS.newBuilder().toResult((SysConfig) o);
+					}
+					SysConfig sysConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, key).last(" limit 1"));
+					if (sysConfig == null) {
+						throw new BusinessRuntimeException("配置不存在");
+					}
+					redisService.set(cacheKey, sysConfig, RedisService.key.SYS_CONFIG_CACHE_KEY.getTimeout());
+					return GatewayResponse.SUCCESS.newBuilder().toResult(sysConfig);
+				} finally {
+					redisService.del(lockKey);
+				}
+			} else {
+				// 未获取锁,返回空
+				throw new BusinessRuntimeException("配置不存在");
+			}
+		} catch (BusinessRuntimeException e) {
+			throw e;
+		} catch (Exception e) {
+			// Redis异常,返回空保护数据库
 			throw new BusinessRuntimeException("配置不存在");
 		}
-
-		//缓存
-		String cacheKey = RedisService.key.SYS_CONFIG_CACHE_KEY.getName() + key;
-		Object o = redisService.get(cacheKey);
-		if (o == null) {
-			redisService.setNx(RedisService.key.SYS_CONFIG_CACHE_KEY.getName() + key, sysConfig, RedisService.key.SYS_CONFIG_CACHE_KEY.getTimeout());
-		}
-		return GatewayResponse.SUCCESS.newBuilder().toResult(sysConfig);
 	}
 
 	@PostMapping("/post")