Skip to content

Commit

Permalink
feat(kv): optimize zset lru cache performance (#280)
Browse files Browse the repository at this point in the history
  • Loading branch information
caojiajun committed Aug 8, 2024
1 parent e5ee2dc commit 59232cd
Showing 1 changed file with 44 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,38 +13,54 @@
public class RedisZSet {

private final Map<BytesKey, Double> memberMap;
private List<ZSetTuple> rank = new ArrayList<>();
private List<ZSetTuple> score = new ArrayList<>();

private boolean sorted;
private final List<ZSetTuple> rank = new ArrayList<>();
private final List<ZSetTuple> score = new ArrayList<>();

public RedisZSet(Map<BytesKey, Double> memberMap) {
this.memberMap = memberMap;
refresh();
sort();
}

public RedisZSet duplicate() {
Map<BytesKey, Double> map = new HashMap<>(memberMap);
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<ZSetTuple> list = new ArrayList<>(memberMap.size());
for (Map.Entry<BytesKey, Double> entry : memberMap.entrySet()) {
list.add(new ZSetTuple(entry.getKey(), entry.getValue()));
}

List<ZSetTuple> 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<ZSetTuple> 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<BytesKey, Double> zadd(Map<BytesKey, Double> map) {
Expand All @@ -55,7 +71,7 @@ public Map<BytesKey, Double> zadd(Map<BytesKey, Double> map) {
existsMap.put(entry.getKey(), put);
}
}
refresh();
onChange();
return existsMap;
}

Expand All @@ -64,6 +80,7 @@ public List<ZSetTuple> zrange(int start, int stop) {
if (rank.isEmptyRank()) {
return Collections.emptyList();
}
sortIfNeed();
start = rank.getStart();
stop = rank.getStop();
List<ZSetTuple> result = new ArrayList<>();
Expand All @@ -85,6 +102,7 @@ public List<ZSetTuple> zrevrange(int start, int stop) {
if (rank.isEmptyRank()) {
return Collections.emptyList();
}
sortIfNeed();
start = rank.getStart();
stop = rank.getStop();
List<ZSetTuple> result = new ArrayList<>();
Expand All @@ -103,6 +121,7 @@ public List<ZSetTuple> 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()) {
Expand All @@ -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);
Expand All @@ -130,6 +150,7 @@ public int zlexcount(ZSetLex minLex, ZSetLex maxLex) {
}

public List<ZSetTuple> zrangebyscore(ZSetScore minScore, ZSetScore maxScore, ZSetLimit limit) {
sortIfNeed();
List<ZSetTuple> result = new ArrayList<>();
int count = 0;
for (ZSetTuple member : score) {
Expand All @@ -152,6 +173,7 @@ public List<ZSetTuple> zrangebyscore(ZSetScore minScore, ZSetScore maxScore, ZSe
}

public List<ZSetTuple> zrevrangeByScore(ZSetScore minScore, ZSetScore maxScore, ZSetLimit limit) {
sortIfNeed();
List<ZSetTuple> result = new ArrayList<>();
int count = 0;
for (int i=this.score.size() - 1; i>=0; i--) {
Expand All @@ -175,6 +197,7 @@ public List<ZSetTuple> zrevrangeByScore(ZSetScore minScore, ZSetScore maxScore,
}

public List<ZSetTuple> zrangeByLex(ZSetLex minLex, ZSetLex maxLex, ZSetLimit limit) {
sortIfNeed();
List<ZSetTuple> result = new ArrayList<>();
int count = 0;
for (ZSetTuple member : this.rank) {
Expand All @@ -194,6 +217,7 @@ public List<ZSetTuple> zrangeByLex(ZSetLex minLex, ZSetLex maxLex, ZSetLimit lim
}

public List<ZSetTuple> zrevrangeByLex(ZSetLex minLex, ZSetLex maxLex, ZSetLimit limit) {
sortIfNeed();
List<ZSetTuple> result = new ArrayList<>();
int count = 0;
for (int i=this.rank.size() - 1; i>=0; i--) {
Expand Down Expand Up @@ -222,6 +246,7 @@ public Pair<Integer, ZSetTuple> zrank(BytesKey member) {
if (v == null) {
return null;
}
sortIfNeed();
for (int i=0; i<rank.size(); i++) {
ZSetTuple tuple = rank.get(i);
if (tuple.getMember().equals(member)) {
Expand All @@ -236,6 +261,7 @@ public Pair<Integer, ZSetTuple> 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)) {
Expand All @@ -259,7 +285,7 @@ public Map<BytesKey, Double> zrem(Collection<BytesKey> members) {
}
}
if (!map.isEmpty()) {
refresh();
onChange();
}
return map;
}
Expand All @@ -277,6 +303,7 @@ public Map<BytesKey, Double> zremrangeByRank(int start, int stop) {
if (rank.isEmptyRank()) {
return new HashMap<>();
}
sortIfNeed();
start = rank.getStart();
stop = rank.getStop();
Map<BytesKey, Double> map = new HashMap<>();
Expand All @@ -292,12 +319,13 @@ public Map<BytesKey, Double> zremrangeByRank(int start, int stop) {
count++;
}
if (!map.isEmpty()) {
refresh();
onChange();
}
return map;
}

public Map<BytesKey, Double> zremrangeByScore(ZSetScore minScore, ZSetScore maxScore) {
sortIfNeed();
Map<BytesKey, Double> map = new HashMap<>();
for (ZSetTuple member : score) {
if (member.getScore() > maxScore.getScore()) {
Expand All @@ -311,12 +339,13 @@ public Map<BytesKey, Double> zremrangeByScore(ZSetScore minScore, ZSetScore maxS
memberMap.remove(member.getMember());
}
if (!map.isEmpty()) {
refresh();
onChange();
}
return map;
}

public Map<BytesKey, Double> zremrangeByLex(ZSetLex minLex, ZSetLex maxLex) {
sortIfNeed();
Map<BytesKey, Double> map = new HashMap<>();
for (ZSetTuple member : rank) {
boolean pass = ZSetLexUtil.checkLex(member.getMember().getKey(), minLex, maxLex);
Expand All @@ -327,7 +356,7 @@ public Map<BytesKey, Double> zremrangeByLex(ZSetLex minLex, ZSetLex maxLex) {
memberMap.remove(member.getMember());
}
if (!map.isEmpty()) {
refresh();
onChange();
}
return map;
}
Expand Down

0 comments on commit 59232cd

Please sign in to comment.