Redis 学习手册(—)

来源:互联网 发布:淘宝店铺头像可以换吗 编辑:程序博客网 时间:2024/06/10 17:17

Redis 学习手册(—)

背景

Redis是一个远程内存数据库,它不仅性能强劲,而且还具有复制特性以及为解决问题而生的独一无二的数据模型。Redis提供了五种不同类型的数据结构,各式各样的问题都可以很自然地映射到这些数据结构上:Redis的数据结构致力于帮助用户解决问题,而不会像其他数据库那样,要求用户扭曲问题来适应数据库。除此之外,通过复制、持久化(persistence)和客户端分片(client-side sharding)等特性,用户可以很方便地将Redis扩展成一个能够包含数百GB数据、每秒钟处理上百万次请求的系统。

注:本人通过学《redis设计与实现》和看源码核对进行总结。

Redis基本数据结构

Redis 提供五种不同类型的数据操作,每种数据操作底层对应了两种算法的支持。根据每种算法在的使用场景,可以自动切换到另一种数据结构。五种算法提供数据底层的内存的存储和查找。用户也可以通过配去更改两种算法的切换阀值。

字符串

顾名思义字符串就是基于字符串的封装。有点类似于C++中的String的封装,相信你如果看过C++库源码的人对于这些的封装并不陌生。将字符串封装成一个结构体,简化使用的逻辑,可以达到复用节约内存等好处。作者其字符串结构重写对于字符串的操作,其目的解决C语言中字符串溢出,缺乏安全等缺点。其主要数据结构的方法如下:

struct sdshdr{  int len;// 记录数组长度  int free;//数组中未使用的字节数量  char buf[];//保存字符串};

链表

链表是一种经常使用的数据结构,这里封装的链表是双向链表。其主要封装方式跟网上和书上介绍的大同小异,具体学习可以参考这里双向链表的实现。这里给出双向链表的基本结构。

typedef struct listNode{struct listNode *prev;//前置节点struct listNode *next;//后置节点void *value;//节点值}listNode;

字典

字典是一种经常被使用的一种数据结构,主要应用于字符串的处理相关操作。Redis中使用hash实现了字典数据结构,解决冲突的方法使用的是链表地址方法。基本数据结构如下:

typedef struct dict {dictType *type; // 类型特定函数void *privatedata;//私有书记dictht ht[2];//hash表int trehashidx;//索引}dict;

跳表

跳表是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。跳表支持平均O(logN)最坏O(N)的复杂度的节点查找,还可以通过顺序性来操作批量处理节点。其数据结构如下:

typedef struct zskiplistNode{struct zskiplistLevel{//层struct zskiplistNode *forward;//前进指针unsigned int span;//跨度}level[];struct zskiplistNode *backward;//后退指针double score;//分值robj *obj;//成员对象}zskiplistNode;

压缩列表

压缩列表是一种特殊的数据结构,专门针对redis开发,通过使用它将多个节点顺序性保存到连续内存中可以有效的降低内存使用。主要数据结构如下:

zlbytes|zltail|zllen|entry1|entry2|....|entryN|zlend|

整数集合

整数集合是一种特殊的数据结构,主要针对整数操作封装出来,其内部使用int16、int32、int64都是非常有考究的。假如你喜欢细节探究可以通过学习源码进一步掌握基本数据结构如下:

typdef struct insert{uint32 encoding;//编码方式uint32 length;//集合包含的数据量int8_t contents[];//保存元素数组}

Redis的基本操作

字符串类型

它可以有三种编码方式:int、raw、embstr。

值 编码 long 类型保存整数 int long double 类型保存浮点数 emstr或raw 字符串长度过大没办法用long类型保存的整数或者长度太大无法用long double 保存的浮点数 emstr或raw

备注:int编码和embstr编码字符串在满足的条件情况下自动转换raw编码字符床。

列表类型

它的编码方式可以是ziplist和linkedlist

列表当满足以下两个条件时,列表对象使用ziplist编码,不满足这个条件的使用linkedlist:

  • 列表保存的所有字符串长度都小于64字节

  • 列表保存元素数量都小于512个

哈希类型

哈希的编码方式可以是ziplist和hashtable

当哈希满足一下两个条件时,哈希会使用ziplist编码,反之依然

  • 所有键值对中的键和值的字符串都满足小于64字节
  • 保存数量小于512个

备注 :上限值可以通过hash-max-ziplist-value和hash-max-ziplist-entries选线修改

集合类型

集合可以使用编码为inset和hashtable。

当集合满足两个条件时,对象使用intsert编码,反之亦然

  • 集合中保存的元素都是整数值
  • 集合中保存元素数量不超过512个

备注:第二个上限值可以通过set-max-intsert-entries修改

有序集合对象

有序集合可以使哟ziplist和skiplist两种编码方式

当有序集合满足两个条件时,对象使用ziplist编码,反之亦然

  • 集合中保存元素数量不超过128个
  • 有序集合中保存的元素长度不超过64个字节

备注:可以通过zset-max-ziplist-entries和zset-max-ziplist-value选项修改

Redis的面向对象使用

虽然Redis使用C语言实现编写,但是底层仍然仿照C++进行设计实现。

内存回收

Redis使用计数原理进行内存块的使用。当计数为0时回收内存,每次操作都进行增加减少。

感觉这里实现有点像C++中的智能指针实现方式,大家可以参考C++中四种智能指针的实现。

多态命令

这里提出来的多态并不是C++中的多态,这里的多态指一个命令可以同时被多个数据结构使用执行。

共享对象

其实这个的实现和内存回收有点像都是通过计数实现,只是共享对象是对接上层,被多个实体共享。

原创粉丝点击