Redis 源码分析(一)

前言

最近一直在预研Redis内存库,下面写的主要是个人的理解,有什么不对地方欢迎大家指正,Redis是依据BSD协议发行的高性能Key-Value存储系统,通常被称为数据结构服务器。

他的值可以是字符串(string),哈希(map),链表(list),集合(sets)和有序集合(sorted sets)等。对于编程新手来说,Redis绝对是学习数据结构非常经典的资料。

下面是官方的解绍

Introduction to Redis

Redis is an open source, advanced key-value store. It is often referred to as adata structure server since keys can containstrings, hashes, lists, sets andsorted sets.

You can run atomic operations on these types, like appending to a string; incrementing the value in a hash; pushing to a list; computing set intersection, union and difference; orgetting the member with highest ranking in a sorted set.

In order to achieve its outstanding performance, Redis works with an in-memory dataset. Depending on your use case, you can persist it either bydumping the dataset to disk every once in a while, or byappending each command to a log.

Redis also supports trivial-to-setup master-slave replication, with very fast non-blocking first synchronization, auto-reconnection on net split and so forth.



先介绍下adlist.h/adlist.c

/* Node, List, and Iterator are the only data structures used currently. */

typedef struct listNode {
    struct listNode *prev;
    struct listNode *next;
    void *value;
}listNode;

typedef struct listIter {
    listNode *next;
    int direction;
}listIter;

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;

listNode 节点下包含prev指针和next指针,说明它通过指针将节点进行双向链接。

list里面声明

/* Prototypes */
list *listCreate(void);
void listRelease(list *list);
list *listAddNodeHead(list *list, void *value);
list *listAddNodeTail(list *list, void *value);
list *listInsertNode(list *list, listNode *old_node, void *value, int after);
void listDelNode(list *list, listNode *node);
listIter *listGetIterator(list *list, int direction);
listNode *listNext(listIter *iter);
void listReleaseIterator(listIter *iter);
list *listDup(list *orig);
listNode *listSearchKey(list *list, void *key);
listNode *listIndex(list *list, long index);
void listRewind(list *list, listIter *li);
void listRewindTail(list *list, listIter *li);
void listRotate(list *list);


下面引用一个对Redis list用途的总结

http://blog.csdn.net/gaogaoshan/article/details/41039581

常用命令:
    lpush,rpush,lpop,rpop,lrange,BLPOP(阻塞版)等。

应用场景:
    Redis list的应用场景非常多,也是Redis最重要的数据结构之一。
    我们可以轻松地实现最新消息排行等功能。
    Lists的另一个应用就是消息队列,可以利用Lists的PUSH操作,将任务存在Lists中,然后工作线程再用POP操作将任务取出进行执行。

实现方式:
    Redis list的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销,Redis内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构。

RPOPLPUSH source destination

    命令 RPOPLPUSH 在一个原子时间内,执行以下两个动作:
    将列表 source 中的最后一个元素(尾元素)弹出,并返回给客户端。
    将 source 弹出的元素插入到列表 destination ,作为 destination 列表的的头元素。
    如果 source 和 destination 相同,则列表中的表尾元素被移动到表头,并返回该元素,可以把这种特殊情况视作列表的旋转(rotation)操作。
    一个典型的例子就是服务器的监控程序:它们需要在尽可能短的时间内,并行地检查一组网站,确保它们的可访问性。
    redis.lpush "downstream_ips", "192.168.0.10"
    redis.lpush "downstream_ips", "192.168.0.11"
    redis.lpush "downstream_ips", "192.168.0.12"
    redis.lpush "downstream_ips", "192.168.0.13"
    Then:
    next_ip = redis.rpoplpush "downstream_ips", "downstream_ips"

BLPOP

  假设现在有 job 、 command 和 request 三个列表,其中 job 不存在, command 和 request 都持有非空列表。考虑以下命令:
  BLPOP job command request 30  #阻塞30秒,0的话就是无限期阻塞,job列表为空,被跳过,紧接着command 列表的第一个元素被弹出。
  1) "command"                             # 弹出元素所属的列表
  2) "update system..."                    # 弹出元素所属的值
  为什么要阻塞版本的pop呢,主要是为了避免轮询。举个简单的例子如果我们用list来实现一个工作队列。执行任务的thread可以调用阻塞版本的pop去获取任务这样就可以避免轮询去检查是否有任务存在。当任务来时候工作线程可以立即返回,也可以避免轮询带来的延迟。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值