diff --git a/camellia-redis-proxy/camellia-redis-proxy-core/src/main/java/com/netease/nim/camellia/redis/proxy/upstream/kv/cache/RedisZSet.java b/camellia-redis-proxy/camellia-redis-proxy-core/src/main/java/com/netease/nim/camellia/redis/proxy/upstream/kv/cache/RedisZSet.java index 7c8d034de..650aa7e77 100644 --- a/camellia-redis-proxy/camellia-redis-proxy-core/src/main/java/com/netease/nim/camellia/redis/proxy/upstream/kv/cache/RedisZSet.java +++ b/camellia-redis-proxy/camellia-redis-proxy-core/src/main/java/com/netease/nim/camellia/redis/proxy/upstream/kv/cache/RedisZSet.java @@ -13,12 +13,14 @@ public class RedisZSet { private final Map memberMap; - private List rank = new ArrayList<>(); - private List score = new ArrayList<>(); + + private boolean sorted; + private final List rank = new ArrayList<>(); + private final List score = new ArrayList<>(); public RedisZSet(Map memberMap) { this.memberMap = memberMap; - refresh(); + sort(); } public RedisZSet duplicate() { @@ -26,25 +28,39 @@ public RedisZSet duplicate() { return new RedisZSet(map); } - private void refresh() { + private void onChange() { + rank.clear(); + score.clear(); + sorted = false; + } + + private void sortIfNeed() { + if (!sorted) { + sort(); + } + } + + private void sort() { List list = new ArrayList<>(memberMap.size()); for (Map.Entry entry : memberMap.entrySet()) { list.add(new ZSetTuple(entry.getKey(), entry.getValue())); } - List rank = new ArrayList<>(list); - rank.sort((o1, o2) -> BytesUtils.compare(o1.getMember().getKey(), o2.getMember().getKey())); - this.rank = rank; + this.rank.clear(); + this.rank.addAll(list); + this.rank.sort((o1, o2) -> BytesUtils.compare(o1.getMember().getKey(), o2.getMember().getKey())); - List score = new ArrayList<>(list); - score.sort((o1, o2) -> { + this.score.clear(); + this.score.addAll(list); + this.score.sort((o1, o2) -> { int compare = Double.compare(o1.getScore(), o2.getScore()); if (compare != 0) { return compare; } return BytesUtils.compare(o1.getMember().getKey(), o2.getMember().getKey()); }); - this.score = score; + + this.sorted = true; } public Map zadd(Map map) { @@ -55,7 +71,7 @@ public Map zadd(Map map) { existsMap.put(entry.getKey(), put); } } - refresh(); + onChange(); return existsMap; } @@ -64,6 +80,7 @@ public List zrange(int start, int stop) { if (rank.isEmptyRank()) { return Collections.emptyList(); } + sortIfNeed(); start = rank.getStart(); stop = rank.getStop(); List result = new ArrayList<>(); @@ -85,6 +102,7 @@ public List zrevrange(int start, int stop) { if (rank.isEmptyRank()) { return Collections.emptyList(); } + sortIfNeed(); start = rank.getStart(); stop = rank.getStop(); List result = new ArrayList<>(); @@ -103,6 +121,7 @@ public List zrevrange(int start, int stop) { } public int zcount(ZSetScore minScore, ZSetScore maxScore) { + sortIfNeed(); int count = 0; for (ZSetTuple member : score) { if (member.getScore() > maxScore.getScore()) { @@ -118,6 +137,7 @@ public int zcount(ZSetScore minScore, ZSetScore maxScore) { } public int zlexcount(ZSetLex minLex, ZSetLex maxLex) { + sortIfNeed(); int count = 0; for (ZSetTuple member : rank) { boolean pass = ZSetLexUtil.checkLex(member.getMember().getKey(), minLex, maxLex); @@ -130,6 +150,7 @@ public int zlexcount(ZSetLex minLex, ZSetLex maxLex) { } public List zrangebyscore(ZSetScore minScore, ZSetScore maxScore, ZSetLimit limit) { + sortIfNeed(); List result = new ArrayList<>(); int count = 0; for (ZSetTuple member : score) { @@ -152,6 +173,7 @@ public List zrangebyscore(ZSetScore minScore, ZSetScore maxScore, ZSe } public List zrevrangeByScore(ZSetScore minScore, ZSetScore maxScore, ZSetLimit limit) { + sortIfNeed(); List result = new ArrayList<>(); int count = 0; for (int i=this.score.size() - 1; i>=0; i--) { @@ -175,6 +197,7 @@ public List zrevrangeByScore(ZSetScore minScore, ZSetScore maxScore, } public List zrangeByLex(ZSetLex minLex, ZSetLex maxLex, ZSetLimit limit) { + sortIfNeed(); List result = new ArrayList<>(); int count = 0; for (ZSetTuple member : this.rank) { @@ -194,6 +217,7 @@ public List zrangeByLex(ZSetLex minLex, ZSetLex maxLex, ZSetLimit lim } public List zrevrangeByLex(ZSetLex minLex, ZSetLex maxLex, ZSetLimit limit) { + sortIfNeed(); List result = new ArrayList<>(); int count = 0; for (int i=this.rank.size() - 1; i>=0; i--) { @@ -222,6 +246,7 @@ public Pair zrank(BytesKey member) { if (v == null) { return null; } + sortIfNeed(); for (int i=0; i zrevrank(BytesKey member) { if (v == null) { return null; } + sortIfNeed(); for (int i=rank.size()-1; i>=0; i--) { ZSetTuple tuple = rank.get(i); if (tuple.getMember().equals(member)) { @@ -259,7 +285,7 @@ public Map zrem(Collection members) { } } if (!map.isEmpty()) { - refresh(); + onChange(); } return map; } @@ -277,6 +303,7 @@ public Map zremrangeByRank(int start, int stop) { if (rank.isEmptyRank()) { return new HashMap<>(); } + sortIfNeed(); start = rank.getStart(); stop = rank.getStop(); Map map = new HashMap<>(); @@ -292,12 +319,13 @@ public Map zremrangeByRank(int start, int stop) { count++; } if (!map.isEmpty()) { - refresh(); + onChange(); } return map; } public Map zremrangeByScore(ZSetScore minScore, ZSetScore maxScore) { + sortIfNeed(); Map map = new HashMap<>(); for (ZSetTuple member : score) { if (member.getScore() > maxScore.getScore()) { @@ -311,12 +339,13 @@ public Map zremrangeByScore(ZSetScore minScore, ZSetScore maxS memberMap.remove(member.getMember()); } if (!map.isEmpty()) { - refresh(); + onChange(); } return map; } public Map zremrangeByLex(ZSetLex minLex, ZSetLex maxLex) { + sortIfNeed(); Map map = new HashMap<>(); for (ZSetTuple member : rank) { boolean pass = ZSetLexUtil.checkLex(member.getMember().getKey(), minLex, maxLex); @@ -327,7 +356,7 @@ public Map zremrangeByLex(ZSetLex minLex, ZSetLex maxLex) { memberMap.remove(member.getMember()); } if (!map.isEmpty()) { - refresh(); + onChange(); } return map; }