初学redis

刚开始看redis..总结一下看到的东西,有些话是参考网上的,有些话是类似自己白话说的,若有不对请指正。

Redis

redis常用五种数据结构:string hash list set sortedset

 

String:(字符串)

一个key对应一个value,是二进制安全的

typedef char *sds;

struct sdshdr {

        int len;// 记录 buf 数组中已使用字节的数量  等于 SDS 所保存字符串的长度

        int free;// 记录 buf 数组中未使用字节的数量

        char buf[];// 字节数组,用于保存字符串

};

一个sds实际申请的内存: sizeof(sdshdr)+len+free+1 刚开始free为0,当需要增长时根据策略进行动态增长

 

List:(列表/双向链表)

typedef struct listNode {

    struct listNode *prev;  //指向前一个节点

    struct listNode *next; //指向后一个节点

void *value;//值

} listNode;//节点

 

typedef struct list {

    listNode *head;//双向链表的头节点

listNode *tail;//双向链表的尾节点

    void *(*dup)(void *ptr);//复制

    void (*free)(void *ptr);//释放

    int (*match)(void *ptr, void *key);//匹配

unsigned long len;//链表长度

} list;//双向链表/列表

typedef struct listIter {

    listNode *next;//指向列表的某个节点

int direction;//迭代方向

} listIter;//访问链表的迭代器

 

Hash:(哈希)

是一个string类型的field和value的映射表,适用于储存对象

Set:(集合)

底层实现是哈希,一般情况使用0号哈希表,如果在rehash时,则会同时使用0号和1号哈希表

哈希表采用链地址法解决键冲突,自动rehash收缩或者扩展哈希表

typedef struct dictEntry {

    void *key; //键

    union {

        void *val;

        uint64_t u64;

        int64_t s64;

    } v; //值

struct dictEntry *next;//指向下一个节点

} dictEntry;//哈希节点

 

typedef struct dictht {

    dictEntry **table; //桶 哈希节点类型

    unsigned long size;//指针数组大小

    unsigned long sizemask;//指针数组掩码,用于计算索引值    

unsigned long used;//hash表现有节点数量

} dictht;//哈希表

 

typedef struct dict {

    dictType *type; //类型处理函数

    void *privdata; //类型处理函数私有值

    dictht ht[2];//两个hash表

int rehashidx; //rehash标示,为-1表示不在rehash,不为0表示正在rehash的桶

int iterators; //当前正在运行的安全迭代器数量

} dict;//集合有2个哈希表

Rehash:创建比ht[0]->table更大的ht[1]->table,size为大于use*2的2的指数,开始值为4,然后把ht[0]的键值对迁移到ht[1]中,将ht[0]中数据清空,将新的ht[1]替代ht[0]。

进行rehash的条件:

自然 rehash : ratio >= 1 ,且变量 dict_can_resize 为真。

强制 rehash : ratio 大于变量 dict_force_resize_ratio (目前版本中, dict_force_resize_ratio 的值为 5 )。

Sorted set:(有序集合)

Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。

不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。

有序集合的成员是唯一的,但分数(score)却可以重复。

typedef struct zskiplistNode {

    robj *obj; // 成员对象

    double score;// 分值

    struct zskiplistNode *backward; // 后退指针

    struct zskiplistLevel {

        struct zskiplistNode *forward; // 前进指针

        unsigned int span;// 跨度

    } level[]; // 层

} zskiplistNode;//有序集合的节点

 

typedef struct zskiplist {

    struct zskiplistNode *header, *tail;  // 表头节点和表尾节点

    unsigned long length;// 表中节点的数量

    int level;// 表中层数最大的节点的层数

} zskiplist;//有序集合

数据库:

Redis客户端默认目标数据库为0号数据库

数据库由dict(保存键值对)和expires(保存键的过期时间)两字典组成

 

RDB持久化

服务器中的非空数据库以及他们的键值对统称为数据库状态。

RDB持久化可将数据库状态保存在磁盘,可手动执行也可定期执行。通过该文件可还原数据库状态。

RDB文件是经过压缩的二进制文件,对于不同类型的键值对,RDB会以不同方式来保存。

SAVE或者BGSAVE可生成rdb文件。

SAVE会阻塞服务器进程,到创建完成前都不能处理任何命令请求。BGSAVE会派生出一个子进程来创建RDB,父进程就可以执行其他命令了。

服务器启动时如果检测到RDB文件就会载入,如果开启了AOF持久化功能,则优先用AOF文件。

AOF持久化

AOF持久化是通过保存redis服务器所执行的写命令来记录数据库状态。

实现:命令追加、文件写入、文件同步

命令追加:服务器执行写命令过后,会将写命令追加到服务器状态缓冲区的末尾。

文件写入与同步:在每次结束一个事件循环前,会考虑将缓冲区的内容写入AOF文件。

 

发布和订阅:

SUBSCRIBE:客户端可以订阅一个或多个频道,成为这些频道的订阅者。每当有客户端向这些频道发消息的时候,频道的所有订阅者都可以收到这条消息。

PSUBSCRIBE:客户端可以订阅一个或多个模式,成为这些模式的订阅者。每当有客户端向这些频道发消息的时候,订阅频道以及与这个频道相匹配的模式的订阅者都会收到消息。

 

事务:redis用multi和exec打包事务

以multi开始exec结束,服务器执行事务期间不会中断去执行其他命令。

redis不支持回滚机制,若一个事务在入队命令过程中,出现了命令不存在或者格式错误则服务器拒绝执行此事务。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章