私の連絡先情報
郵便メール:
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
スピン
- public Map<String, List<Catelog2Vo>> getCatalogJsonFromDBWithRedisLock() {
-
- Boolean b = redisTemplate.opsForValue().setIfAbsent(Lock, Lock, Duration.ofMinutes(1));
- if (!b) {
- int i = 10;
- while (i > 0) {
- Object result = redisTemplate.opsForValue().get(CATALOG_JSON);
- try {
- TimeUnit.MILLISECONDS.sleep(100);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- if (result != null) {
- System.out.println("命中缓存 db lock");
- return (Map<String, List<Catelog2Vo>>) result;
- }
- i--;
- }
- throw new RuntimeException("系统繁忙,请重新访问");
- }
-
-
- //1.查出所有1级分类
- List<CategoryEntity> selectList = baseMapper.selectList(null);
- /**
- * 将数据库的多次查询变成一次
- */
- System.out.println("查询了数据库");
-
- //2. 封装数据
- List<CategoryEntity> level1Category = selectList.stream().filter(s -> s.getParentCid().equals(0L)).collect(Collectors.toList());
- Map<String, List<Catelog2Vo>> map = level1Category.stream().collect(Collectors.toMap(k -> k.getCatId().toString(), v -> {
- //1.每一个的一级分类,查到1级分类的所有二级分类
- List<CategoryEntity> categoryEntities = selectList.stream().filter(s -> s.getParentCid().equals(v.getCatId())).collect(Collectors.toList());
-
- List<Catelog2Vo> catelog2VoList = categoryEntities.stream().map(c -> {
- Catelog2Vo catelog2Vo = new Catelog2Vo();
- catelog2Vo.setId(c.getCatId().toString());
- catelog2Vo.setName(c.getName());
- catelog2Vo.setCatalog1Id(v.getCatId().toString());
-
- List<CategoryEntity> categoryEntities1 = selectList.stream().filter(s -> s.getParentCid().equals(c.getCatId())).collect(Collectors.toList());
- List<Catelog2Vo.Catelog3Vo> collect = categoryEntities1.stream().map(c3 -> {
- Catelog2Vo.Catelog3Vo catelog3Vo = new Catelog2Vo.Catelog3Vo();
- catelog3Vo.setId(c3.getCatId().toString());
- catelog3Vo.setName(c3.getName());
- catelog3Vo.setCatalog2Id(c.getCatId().toString());
- return catelog3Vo;
- }).collect(Collectors.toList());
-
- catelog2Vo.setCatalog3List(collect);
-
- return catelog2Vo;
- }).collect(Collectors.toList());
-
-
- return catelog2VoList;
- }));
- if (map == null) {
- /**
- * 解决缓存穿透
- */
- map = new HashMap<>();
- }
- redisTemplate.opsForValue().set(CATALOG_JSON, map, Duration.ofDays(1));
- redisTemplate.delete(Lock);
- return map;
- }
- public Map<String, List<Catelog2Vo>> getCatalogJsonFromDBWithRedisLock() {
- String uuid = UUID.randomUUID().toString();
- Boolean b = redisTemplate.opsForValue().setIfAbsent(Lock, uuid, Duration.ofMinutes(1));
- if (!b) {
- int i = 10;
- while (i > 0) {
- Object result = redisTemplate.opsForValue().get(CATALOG_JSON);
- try {
- TimeUnit.MILLISECONDS.sleep(100);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- if (result != null) {
- System.out.println("命中缓存 db lock");
- return (Map<String, List<Catelog2Vo>>) result;
- }
- i--;
- }
- throw new RuntimeException("系统繁忙,请重新访问");
- }
-
-
- //1.查出所有1级分类
- List<CategoryEntity> selectList = baseMapper.selectList(null);
- /**
- * 将数据库的多次查询变成一次
- */
- System.out.println("查询了数据库");
-
- //2. 封装数据
- List<CategoryEntity> level1Category = selectList.stream().filter(s -> s.getParentCid().equals(0L)).collect(Collectors.toList());
- Map<String, List<Catelog2Vo>> map = level1Category.stream().collect(Collectors.toMap(k -> k.getCatId().toString(), v -> {
- //1.每一个的一级分类,查到1级分类的所有二级分类
- List<CategoryEntity> categoryEntities = selectList.stream().filter(s -> s.getParentCid().equals(v.getCatId())).collect(Collectors.toList());
-
- List<Catelog2Vo> catelog2VoList = categoryEntities.stream().map(c -> {
- Catelog2Vo catelog2Vo = new Catelog2Vo();
- catelog2Vo.setId(c.getCatId().toString());
- catelog2Vo.setName(c.getName());
- catelog2Vo.setCatalog1Id(v.getCatId().toString());
-
- List<CategoryEntity> categoryEntities1 = selectList.stream().filter(s -> s.getParentCid().equals(c.getCatId())).collect(Collectors.toList());
- List<Catelog2Vo.Catelog3Vo> collect = categoryEntities1.stream().map(c3 -> {
- Catelog2Vo.Catelog3Vo catelog3Vo = new Catelog2Vo.Catelog3Vo();
- catelog3Vo.setId(c3.getCatId().toString());
- catelog3Vo.setName(c3.getName());
- catelog3Vo.setCatalog2Id(c.getCatId().toString());
- return catelog3Vo;
- }).collect(Collectors.toList());
-
- catelog2Vo.setCatalog3List(collect);
-
- return catelog2Vo;
- }).collect(Collectors.toList());
-
-
- return catelog2VoList;
- }));
- if (map == null) {
- /**
- * 解决缓存穿透
- */
- map = new HashMap<>();
- }
- redisTemplate.opsForValue().set(CATALOG_JSON, map, Duration.ofDays(1));
- Object o = redisTemplate.opsForValue().get(Lock);
- if (o != null && o.equals(uuid)) {
- redisTemplate.delete(Lock);
- }
-
- return map;
- }
まだ問題があります
送信処理に時間がかかるため、この時点で KEY の有効期限が切れた場合は、他のスレッドに KEY を作成させてから、前のスレッドにデータを返します。KEY が削除されると、他の人が新たに追加したキーが削除されます。削除されました。
値の比較を取得 + 比較が成功した場合は削除 = アトミック操作
redis+luaスクリプトの実装
public static final String Lock = "Lock";
- public Map<String, List<Catelog2Vo>> getCatalogJsonFromDBWithRedisLock() {
- String uuid = UUID.randomUUID().toString();
- Boolean b = redisTemplate.opsForValue().setIfAbsent(Lock, uuid, Duration.ofMinutes(5));
- if (!b) {
- System.out.println("获取分布式锁失败,等待重试");
- int i = 10;
- while (i > 0) {
- Object result = redisTemplate.opsForValue().get(CATALOG_JSON);
- try {
- TimeUnit.MILLISECONDS.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- if (result != null) {
- System.out.println("命中缓存 db lock");
- return (Map<String, List<Catelog2Vo>>) result;
- }
- i--;
- }
- throw new RuntimeException("系统繁忙,请重新访问");
- }
-
-
- //1.查出所有1级分类
- /**
- * 将数据库的多次查询变成一次
- */
- System.out.println("获取分布式锁成功");
-
- //2. 封装数据
- Map<String, List<Catelog2Vo>> map = null;
- try {
- System.out.println("查询了数据库");
- List<CategoryEntity> selectList = baseMapper.selectList(null);
- List<CategoryEntity> level1Category = selectList.stream().filter(s -> s.getParentCid().equals(0L)).collect(Collectors.toList());
- map = level1Category.stream().collect(Collectors.toMap(k -> k.getCatId().toString(), v -> {
- //1.每一个的一级分类,查到1级分类的所有二级分类
- List<CategoryEntity> categoryEntities = selectList.stream().filter(s -> s.getParentCid().equals(v.getCatId())).collect(Collectors.toList());
-
- List<Catelog2Vo> catelog2VoList = categoryEntities.stream().map(c -> {
- Catelog2Vo catelog2Vo = new Catelog2Vo();
- catelog2Vo.setId(c.getCatId().toString());
- catelog2Vo.setName(c.getName());
- catelog2Vo.setCatalog1Id(v.getCatId().toString());
-
- List<CategoryEntity> categoryEntities1 = selectList.stream().filter(s -> s.getParentCid().equals(c.getCatId())).collect(Collectors.toList());
- List<Catelog2Vo.Catelog3Vo> collect = categoryEntities1.stream().map(c3 -> {
- Catelog2Vo.Catelog3Vo catelog3Vo = new Catelog2Vo.Catelog3Vo();
- catelog3Vo.setId(c3.getCatId().toString());
- catelog3Vo.setName(c3.getName());
- catelog3Vo.setCatalog2Id(c.getCatId().toString());
- return catelog3Vo;
- }).collect(Collectors.toList());
-
- catelog2Vo.setCatalog3List(collect);
-
- return catelog2Vo;
- }).collect(Collectors.toList());
-
-
- return catelog2VoList;
- }));
- if (map == null) {
- /**
- * 解决缓存穿透
- */
- map = new HashMap<>();
- }
- redisTemplate.opsForValue().set(CATALOG_JSON, map, Duration.ofDays(1));
-
-
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- //lua脚本解锁
- //如果获取key等于传过来的值,就执行删除操作,否则就不执行
- String script="if redis.call('get',KEYS[1])==ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";
- Long execute = redisTemplate.execute(new DefaultRedisScript<Long>(script, Long.class), Arrays.asList(Lock), uuid);
- if (execute==1){
- System.out.println("原子删锁成功");
- }else {
- System.out.println("原子删锁失败");
- }
- }
-
- return map;
- }
データベースにクエリを実行したのは 1 つだけです