前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >redis 命令exists vs get

redis 命令exists vs get

原创
作者头像
zeekling
发布2022-11-11 00:30:11
1.1K0
发布2022-11-11 00:30:11
举报
文章被收录于专栏:浪浪山下那个村

功能对比

exists

参数格式:

代码语言:javascript
复制
EXISTS key [key ...]

用于判断某个键是否存在

get

参数格式:

代码语言:javascript
复制
GET key

用于获取键对应的值。

由上可知,相同的场景只有判断键是否存在。

性能对比

使用下面命令向Redis里面注入大量数据:

代码语言:javascript
复制
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);
    }

}

使用下面代码对比相应时间:

代码语言:javascript
复制
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();
 }

}

执行结果如下:

代码语言:javascript
复制
get cost=476
exists cost=279

由此可见,get性能要比exists差。

源码分析

get命令核心查找key代码

代码语言:javascript
复制
robj *lookupKeyReadOrReply(client *c, robj *key, robj *reply) {
    robj *o = lookupKeyRead(c->db, key);
    if (!o) addReply(c,reply);
    return o;
}

其中lookupKeyRead的实现:

代码语言:javascript
复制
robj *lookupKeyRead(redisDb *db, robj *key) {
    return lookupKeyReadWithFlags(db,key,LOOKUP_NONE);
}

exists命令核心实现:

代码语言:javascript
复制
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,我们看下这个函数的实现:

代码语言:javascript
复制
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;
}

可见都是先判断了确认了是否过期(过期key单独保存在另一个dict里面),再没有过期的情况下查找了db库,总体查找时间是一致的。

但是,我们可以发现,get命令返回了键对应的值,exists返回了个数,一般键对应的值较大,传输时间较长。所以相对较慢。

结论

在判断key是否存在的场景下:

  • exists速度更快,可以忽略类型。
  • get只适用于string类型,当值越大时,速度越慢。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 功能对比
    • exists
      • get
      • 性能对比
      • 源码分析
      • 结论
      相关产品与服务
      云数据库 Redis
      腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档