`

redis之字符串命令源码解析(三)

阅读更多

形象化设计模式实战             HELLO!架构

 

redis之字符串命令源码解析(一)

redis之字符串命令源码解析(二)

 

 

前面已经将set get命令的原理与过程作了详细的解析,下面对一些常用的命令做一些简单讲解,前提是前面的已经明白。

1、append方法解析

 
t_string.c中的appendCommand方法:
void appendCommand(redisClient *c) {
    size_t totlen;
    robj *o, *append;

    // 取出键相应的值对象
    o = lookupKeyWrite(c->db,c->argv[1]);
    // 如果键值对不存在
    if (o == NULL) {
        // 键值对不存在,创建一个新的
        c->argv[2] = tryObjectEncoding(c->argv[2]);
        dbAdd(c->db,c->argv[1],c->argv[2]);
        incrRefCount(c->argv[2]);
        //获取字符串对象中字符串值的长度
        totlen = stringObjectLen(c->argv[2]);
    } else {

        // 键值对存在。。。

        /* Key exists, check type */
        // 检查类型
        if (checkType(c,o,REDIS_STRING))
            return;

        /* "append" is an argument, so always an sds */
        // 检查追加操作之后,字符串的长度是否符合 Redis 的限制
        append = c->argv[2];
        totlen = stringObjectLen(o)+sdslen(append->ptr);
        //检查给定字符串长度 len 是否超过限制值 512 MB
        if (checkStringLength(c,totlen) != REDIS_OK)
            return;

        //解除key的共享,之后就可以进行修改操作(采用的方法是新建一个robj对象,覆盖掉原有的)
        o = dbUnshareStringValue(c->db,c->argv[1],o);
        //执行追加操作
        o->ptr = sdscatlen(o->ptr,append->ptr,sdslen(append->ptr));
        totlen = sdslen(o->ptr);
    }

    // 向数据库发送键被修改的信号
    signalModifiedKey(c->db,c->argv[1]);

    // 发送事件通知
    notifyKeyspaceEvent(REDIS_NOTIFY_STRING,"append",c->argv[1],c->db->id);

    // 将服务器设为脏
    server.dirty++;

    // 发送回复(字符的长度)
    addReplyLongLong(c,totlen);
}
大致可图解为:

2、incrby方法解析

void incrbyCommand(redisClient *c) {
    long long incr;

    //将第二个参数转化成long long类型,指向incr
    if (getLongLongFromObjectOrReply(c, c->argv[2], &incr, NULL) != REDIS_OK) return;
    incrDecrCommand(c,incr);
}

void incrDecrCommand(redisClient *c, long long incr) {
    long long value, oldvalue;
    robj *o, *new;

    // 取出值对象
    o = lookupKeyWrite(c->db,c->argv[1]);

    // 检查对象是否存在,以及类型是否正确
    if (o != NULL && checkType(c,o,REDIS_STRING)) return;

    // 取出对象的整数值,并保存到 value 参数中
    if (getLongLongFromObjectOrReply(c,o,&value,NULL) != REDIS_OK) return;

    // 检查加法操作执行之后值释放会溢出
    // 如果是的话,就向客户端发送一个出错回复,并放弃设置操作
    oldvalue = value;
    if ((incr < 0 && oldvalue < 0 && incr < (LLONG_MIN-oldvalue)) ||
        (incr > 0 && oldvalue > 0 && incr > (LLONG_MAX-oldvalue))) {
        addReplyError(c,"increment or decrement would overflow");
        return;
    }

    // 进行加法计算,并将值保存到新的值对象中
    // 然后用新的值对象替换原来的值对象
    value += incr;
    new = createStringObjectFromLongLong(value);
    if (o)
        dbOverwrite(c->db,c->argv[1],new);
    else
        dbAdd(c->db,c->argv[1],new);

    // 向数据库发送键被修改的信号
    signalModifiedKey(c->db,c->argv[1]);

    // 发送事件通知
    notifyKeyspaceEvent(REDIS_NOTIFY_STRING,"incrby",c->argv[1],c->db->id);

    // 将服务器设为脏
    server.dirty++;

    // 返回回复
    addReply(c,shared.colon);
    addReply(c,new);
    addReply(c,shared.crlf);
}

大致可图解为:
 
这里说下“addReply(c,shared.colon);”这行代码,shared.colon是什么?
Redis 在内部使用了一个Flyweight 模式:通过预分配一些常见的值对象,并在多个数据结构之间共享这些对象,程序避免了重复分配的麻烦,也节约了一些CPU时间。redis.c的createSharedObjects创建了shared
shared.colon = createObject(REDIS_STRING,sdsnew(":"));
由可见如果运行incrby test 3,如果test不存在,那么服务器返回的应该是":3\r\n",可以用telnet连接试试。
 
 
总体来看,Redis的结构设计得有许多巧妙之处,为实现字符串各种需求打下了很好的基础,后序还将剖析Redis相比memcache比较特殊的结构。

 

5
5
分享到:
评论

相关推荐

    Redis源码解析

    源码解析有助于深入理解其工作原理,提高在实际应用中的优化能力。本篇文章将聚焦Redis的源码,探讨其核心组件、数据结构以及内部运行机制。 1. **Redis的数据结构** Redis的核心数据结构包括字符串(String)、...

    Redis实战中文版及源码下载

    2. **丰富的数据结构**:Redis提供了多种数据结构,如字符串、哈希、列表、集合、有序集合,这些数据结构在处理各种复杂应用场景时非常实用。例如,哈希可用于存储对象,列表可以实现消息队列,有序集合则适用于排行...

    Redis Windows源码

    Redis支持多种数据结构,如字符串、哈希表、列表、集合和有序集合。这些数据结构的实现是Redis高效性的关键。例如,链表、跳跃表(用于有序集合的快速查找)和压缩表(用于节省内存)等都是Redis内部的重要组件。 ...

    redis3源码及解析

    Redis源码解析是一项深入学习数据库系统、内存管理以及并发控制等核心计算机科学概念的宝贵资源。 首先,我们来看Redis中的核心数据结构。Redis支持多种数据类型,包括字符串(String)、哈希表(Hash)、列表...

    redis delphi实施数据库操作源码

    这通常涉及解析响应的类型(简单字符串、错误、整数、多条批量数据等)。例如,获取键的值: ```pascal var Response: string; begin RedisClient.SendCommand('GET', ['mykey']); if RedisClient.GetResponse...

    易语言源码Redis协议客户端易语言模块源码.rar

    它主要包含三种数据类型:简单的字符串(Simple Strings)、错误(Errors)、整数(Integers)、大整数(Bulk Strings)和多条数据(Multi-Bulk)。在易语言源码中,你会看到如何将这些数据类型转化为易语言的数据...

    redis-unstable_Redis数据库源码_

    Redis使用多种自定义的数据结构来存储和操作数据,如字符串(String)、哈希表(Hash)、列表(List)、集合(Set)和有序集合(Sorted Set)。这些数据结构在源码中都有对应的实现,例如` SDS (Simple Dynamic ...

    Redis安装包X64及源码.rar

    1. 数据结构:Redis的核心在于其高效的数据结构,如字符串、哈希表、链表、集合和有序集合等,这些都是C++实现的。 2. 异步I/O:Redis采用单线程模型处理所有客户端请求,通过事件驱动的非阻塞I/O(epoll、kqueue等...

    redis视频以及代码

    1. 键值对(Key-Value):Redis的核心存储结构,键是唯一的标识,值可以是多种类型,如字符串、哈希、列表、集合和有序集合。 2. 数据类型: - 字符串(String):最基础的类型,可存储整数、浮点数或任意文本。 ...

    redis-5.0.14.源码

    1. **数据结构**:Redis 的核心在于其高效的数据结构实现,如字符串(String)、哈希表(Hash)、列表(List)、集合(Set)和有序集合(Sorted Set)。这些数据结构的实现通常采用内存优化的方式,如 SDS(Simple ...

    redis in action 源码

    源码的阅读可以帮助我们深入理解Redis如何处理数据结构(如字符串、哈希表、列表、集合、有序集合等)、命令执行、持久化机制(RDB和AOF)、网络I/O模型(基于epoll的事件驱动)以及复制和集群功能。 首先,Redis的...

    redis源码日志(源码分析)

    同时,通过精心设计的数据结构(如哈希表、链表、跳跃表等)和编码方式(如SDS代替C字符串)来减少内存占用。 3. **命令执行原子性**:Redis的所有操作都是原子性的,即每个命令的执行不会被其他命令打断,保证了...

    labview redis通讯源码及实例

    LabVIEW程序需要正确构建这些命令的字符串格式并发送到Redis服务器。 3. **数据序列化与反序列化**:由于LabVIEW是基于图形的,而Redis处理的是字符串,所以数据在两者之间传输时,需要进行序列化和反序列化。例如...

    Redis_redis_源码

    1. **Redis的数据结构**:Redis支持多种数据结构,如字符串(Strings)、哈希表(Hashes)、列表(Lists)、集合(Sets)和有序集合(Sorted Sets)。这些数据结构的设计使得Redis在处理复杂数据操作时非常高效。 2...

    redis 学习 基础知识 源码

    本文将深入探讨 Redis 的基础知识,包括其核心概念、数据类型、命令操作以及源码解析。 ### 1. Redis 核心概念 Redis 作为内存数据库,所有数据存储在内存中,通过持久化策略将数据保存到磁盘以防止数据丢失。其...

    redis-4.0.14源码压缩包

    - **字符串(Strings)**:简单动态字符串(SDS)是Redis内部实现的字符串,提供预分配空间、长度计算等功能,比C语言的原始字符串更高效。 - **列表(Lists)**:可以使用quicklist或linked list实现,前者是优化...

    redis源码分析

    Redis支持多种数据结构,如字符串(String)、哈希表(Hash)、列表(List)、集合(Set)和有序集合(Sorted Set)。这些数据结构在源码中由不同的C结构体实现,例如`sds`用于表示字符串,`dict`表示哈希表,`list`...

    redis in action源码

    - 源码中包含了Redis服务器的核心实现,如命令解析、数据结构操作、持久化、网络通信等。 - `redis.c`是主程序,负责初始化和事件循环。 - `server.h`和`server.c`定义了服务器状态和主要功能。 - `networking.c...

    源码redis2.6中文注释版

    1. 字符串:Redis的基础数据类型,使用`sds`(Simple Dynamic Strings)实现,具备预分配空间和O(1)的修改操作。 2. 哈希表:用于存储键值对,采用开放寻址法解决冲突,源码在`dict.c`中。 3. 列表:支持双向链表,...

Global site tag (gtag.js) - Google Analytics