zoukankan      html  css  js  c++  java
  • Redis

    吃住Redis

    • Redis入门指南

    • Redis设计与实现

    • Redis实战

    基本类型

    字符串类型 SDS (simple dynamic string)

    还被用作缓冲区:AOF中的AOF缓冲区,客户端状态中的输入缓冲区

    c字符串作为字符串字面量(string literal)用在一些无须对字符串值进行修改的地方,如打印日志.

    Redis使用sdshdr类型变量来存储字符串,redisObject的ptr字段指向的是该变量的地址
    
        struct sdshdr{
            int len;//字符串长度,buf数组已使用字节数量
            int free;//buf中剩余空间
            char buf[];//存储字符串内容  字节数组
        }
    

    sds相较于c字符串的好处:

    • 常数复杂度获取字符串长度

    • 杜绝缓冲区溢出

    • 减少修改字符串时带来的内存重分配次数

      • 空间预分配: 对sds空间扩展时,会为sds分配额外的未使用空间

        • 如果修改后sds长度小于1MB,则分配和len属性同样大小的未使用空间.

          如: 修改后sds的len变成13字节,那么sds的buf长度会变成13+13+1=27字节

        • 如果修改后sds长度大于1MB,则分配1MB空间.

          如: 修改后sds的len变成30MB,那么sds的buf长度会变成30MB+1MB+1btyte=27字

      • 惰性空间释放: 缩短sds保存的字符串时,使用free属性记录下来,等待将来使用.

    • 二进制安全

    链表

    列表键的底层实现之一就是链表: 当一个列表键包含了数量比较多的元素,或者链表包含的元素都是比较长的字符串时,redis就会使用链表作为列表键的实现.

    此外 发布订阅,慢查询,监视器等功能也用到了链表,redis服务器用链表保存多个客户端的状态信息,用链表来构建客户端输出缓冲区.

    typedef struct listNode{
        struct listNode *prev;
        struct listNode *next;
        void *value;
    }listNode;
    
    typedef struct list{
        listNode *head;
        listNode *tail;
        unsigned long len;
        void *(*dup)(void *ptr);	//节点复制函数
        void *(*free)(void *ptr);//节点释放函数
        void *(*match)(void *ptr, void *key);//节点对比函数
    }list;
    
    • Redis链表特性
      • 双端: 获取某个节点的前置和后置节点复杂度都是O(1)
      • 无环: 表头节点的prev和表尾节点的next都指向NULL
      • 有表头表位指针.O(1)获取
      • 长度计数器
      • 多态,可以保存各种不同类型的值

    字典

    又称 关联数组,映射,符号表. 用于保存键值对, 一个键和一个值关联

    字典用来表示数据库, 也是哈希键的底层实现之一: 当一个哈希键包含的键值对比较多,或者键值对中的元素都是比较长的字符串时,Redis就会使用字典作为哈希键的底层实现.

    字典使用哈希表作为底层实现.

    typedef struct dictht{
        dictEntry **table;//哈希表数组
        unsigned long size;//哈希表大小
        unsigned long sizemask;//哈希表大小掩码,用于计算索引值,总是等于size-1
        unsigned long used;//哈希表已有节点的数量
    } dictht;
    

    sizemask和哈希值一起决定一个键应该被放到table数组的哪个索引上

    typedef struct dictEntry{
        void *key;
        union{
            void *val;
            uint64_t u64;
            int64_t s64;
        } v;
        struct dictEntry *next;//可以将多个哈希值相同的键值连接在一起,解决键冲突问题
    } dictEntry;
    

    键值可以是一个指针,一个uint64_t整数或一个int64_t整数

    Redis的字典:

    typedef struct dict {
        dictType *type;     //类型特定函数
        void *privdata;     //私有数据
        dictht ht[2];       //哈希表
        int trehashidx;     //rehash索引
    } dict;
    

    Redis键 总是一个字符串对象string object

    Redis键值都是用redisObject结构体保存的

    typedef struct redisObject{
        unsigned type:4;
        unsigned notused:2;
        unsigned encoding:4;
        unsigned lru:22;  //lru time (relative to server.lrulock)
        int refcount; //该键值被引用数量
        void *ptr;
    } robj;
    

    type是键值数据类型,取值:

    #define REDIS_STRING 0
    #define REDIS_LIST 1
    #define REDIS_SET 2
    #define REDIS_ZSET 3
    #define REDIS_HASH 4
    

    encoding表示Redis键值的内部编码方式,取值

    #define REDIS_ENCODING_RAW 0
    #define REDIS_ENCODING_INT 1
    #define REDIS_ENCODING_HT 2             //hash table
    #define REDIS_ENCODING_ZIPMAP 3
    #define REDIS_ENCODING_LINKEDLIST 4
    #define REDIS_ENCODING_ZIPLIST 5
    #define REDIS_ENCODING_INTSET 6
    #define REDIS_ENCODING_SKIPLIST 7
    #define REDIS_ENCODING_EMBSTR 8         //embeded sds string encoding
    
    执行set key foobar时,存储键值占用的空间是:
        sizeof(redisObject) + sizeof(sdshdr) + strlen("foobar") = 30字节
    执行set key 123456时,占用空间是:
        sizeof(redisObject) = 16字节
    

    Redis启动后会预先建立10000个 从0到9999这些数字的redisObject类型变量作为共享对象.
    如果要设置的字符串键值在这范围内,则直接引用共享变量而不用再建立一个redisObject
    存储键值占用0字节

    当配置文件参数maxmemory设置了Redis可用的最大空间大小时,Redis不会使用共享变量.
    因为对于每一个键值都需要使用一个redisObject来记录其lru信息

    事物

    脚本

    持久化

    复制 (replication)

    master  读写
    slave   只读
    
    在从数据库的配置文件加入slaveof 主数据库地址 主数据库端口
    使用info replication 获取相关信息
    slaveof no one 使从数据库变成主数据库
    
    当一个从数据库启动后,会向主数据库发送sync命令,主数据库接收到sync命令后,
    开始在后台保存快照(RDB持久化),并将保存快照期间接收到的命令缓存起来,当快照
    完成时,Redis会将快照文件和所有缓存的命令发送给从数据库.
    
    从数据库收到后,会载入快照文件并执行收到的缓存的命令.
    

    哨兵 (sentinel)

    集群 (cluster)

  • 相关阅读:
    Qt 学习之路:Canvas
    Qt 学习之路:模型-视图高级技术
    Qt 学习之路 :视图代理
    Qt 学习之路 :动态视图
    Qt 学习之路 :Repeater
    Qt 学习之路 :Qt Quick Controls
    mysql-gdb--oracle
    redis-BOOK
    2016qconbeijing
    LINUX 内核月报 taobao
  • 原文地址:https://www.cnblogs.com/R4mble/p/10026131.html
Copyright © 2011-2022 走看看