redis 命令exists vs get
功能對比
exists
參數格式:
EXISTS key [key ...]
用于判斷某個(gè)鍵是否存在
get
參數格式:
GET key
用于獲取鍵對應的值。
由上可知,相同的場(chǎng)景只有判斷鍵是否存在。
性能對比
使用下面命令向Redis里面注入大量數據:
public class FillData {
private static final Jedis jedis = new Jedis("127.0.0.1", 6379);
private static void fillData(long min, long max, SetParams params) {
for (long i = min; i < max; i++) {
jedis.set("key_0000000" + i, "value_0000000" + i, params);
if (i % 1000 == 0) {
System.out.println("count=" + i);
}
}
}
public static void main(String[] args) {
SetParams params = new SetParams();
FillData.fillData(0, 5000000, params);
params.ex(50000L);
FillData.fillData(50000000, 55000000, params);
}
}
使用下面代碼對比相應時(shí)間:
public class ExistsVSGet {
private static final Jedis jedis = new Jedis("127.0.0.1", 6379);
private static void exists() {
long begin = System.nanoTime();
jedis.exists("key_aaaaaaa");
long end = System.nanoTime();
System.out.println("exists cost=" + (end - begin)/1000);
}
private static void get() {
long begin = System.nanoTime();
jedis.exists("key_aaaaaaa");
long end = System.nanoTime();
System.out.println("get cost=" + (end - begin)/1000);
}
private static void test() {
for (int i=1; i< 10; i++) {
jedis.get("0000000" + i);
}
}
public static void main(String[] args) {
ExistsVSGet.test();
ExistsVSGet.get();
ExistsVSGet.exists();
}
}
執行結果如下:
get cost=476
exists cost=279
由此可見(jiàn),get性能要比exists差。
源碼分析
get命令核心查找key代碼
robj *lookupKeyReadOrReply(client *c, robj *key, robj *reply) {
robj *o = lookupKeyRead(c->db, key);
if (!o) addReply(c,reply);
return o;
}
其中lookupKeyRead的實(shí)現:
robj *lookupKeyRead(redisDb *db, robj *key) {
return lookupKeyReadWithFlags(db,key,LOOKUP_NONE);
}
exists命令核心實(shí)現:
void existsCommand(client *c) {
long long count = 0;
int j;
for (j = 1; j < c->argc; j++) {
if (lookupKeyReadWithFlags(c->db,c->argv[j],LOOKUP_NOTOUCH)) count++;
}
addReplyLongLong(c,count);
}
exists和get命令都調用了lookupKeyReadWithFlags,我們看下這個(gè)函數的實(shí)現:
robj *lookupKeyReadWithFlags(redisDb *db, robj *key, int flags) {
robj *val;
if (expireIfNeeded(db,key) == 1) {
if (server.masterhost == NULL)
goto keymiss;
if (server.current_client &&
server.current_client != server.master &&
server.current_client->cmd &&
server.current_client->cmd->flags & CMD_READONLY)
{
goto keymiss;
}
}
val = lookupKey(db,key,flags);
if (val == NULL)
goto keymiss;
server.stat_keyspace_hits++;
return val;
keymiss:
if (!(flags & LOOKUP_NONOTIFY)) {
server.stat_keyspace_misses++;
notifyKeyspaceEvent(NOTIFY_KEY_MISS, "keymiss", key, db->id);
}
return NULL;
}
可見(jiàn)都是先判斷了確認了是否過(guò)期(過(guò)期key單獨保存在另一個(gè)dict里面),再沒(méi)有過(guò)期的情況下查找了db庫,總體查找時(shí)間是一致的。
但是,我們可以發(fā)現,get命令返回了鍵對應的值,exists返回了個(gè)數,一般鍵對應的值較大,傳輸時(shí)間較長(cháng)。所以相對較慢。
結論
在判斷key是否存在的場(chǎng)景下:
- exists速度更快,可以忽略類(lèi)型。
- get只適用于string類(lèi)型,當值越大時(shí),速度越慢。

0 評論