Redis笔记



Redis


2、简单动态字符串:SDS
SET msg "hello world"


struct sdshdr{
int len; //长度
int free; //可用空间
char buf[]; //内容
}
SDS最后一个字符为'\0';
空间预分配:
当空间不足时,如果修改后,SDS的长度将小于1MB,那么程序分配和len属性同样大小的未使用空间;
如果长度大于等于1MB,那么程序会分配1MB的未使用空间;
SDS的API都是二进制安全的,所有SDS API都会以处理二进制的方式来处理SDS存放在buf数组里的数据。
3、链表
LLEN myList
LRANGE myList 0 10 //获取链表前10个元素
typeof struct listNode{
struct listNode *prev; //前置节点
struct listNode *next; //后置节点
void *value; //节点的值
}
typeof struct list{
listNode *head; //表头节点
listNode *tail; //表尾节点
unsigned long len; //链表所包含的节点数量
void *(*dup)(void *ptr); //节点值复制函数
void *(*free)(void *ptr); //节点值释放函数
int (*match)(void *ptr, void *key); //节点值对比函数
}list;
4、字典
HLEN myMap
HGETALL myMap
哈希表
typeof struct dictht{
dictEntry **table; //哈希表数组
unsigned long size; //哈希表大小
unsigned long sizemask; //哈希表大小掩码,用于计算索引值,总是等于size-1
unsigned long used; //哈希表已有节点的数量
}dictht;
哈希表节点
typeof struct dictEntry{
void *key; //键
union{ //值
void *val;
uint64_t u64;
int64_t s64;
}v;
struct dictEntry *next; //指向哈希表节点,形成链表;
}dicEntry;


字典
typeof struct dict{
dictType *type; //类型特定函数
void *privdata; //私有数据
dictht ht[2]; //哈希表
int trehashidx; //rehash索引,当rehash不在进行时,值为-1;
}dict;
type struct dictType{
函数
...
}
解决键冲突:一个键上对应一个链表,可以保存多个值;
rehash:重新散列哈希表;
5、跳跃表:一种有序数据结构;
ZRANGE fruit-price 0 2 WITHSCORES
跳跃表节点
typedef struct zskiplistNode{
//层
struct zskiplistLevel{
struct zskiplistNode *forward; //前进指针
unsigned int span; //跨度
}level[];
struct zskiplistNode *backward; //后退指针
double score; //排序分值
robj *obj; //成员对象
}zskiplistNode;
跳跃表结构
typedef struct zskiplist{
structz skiplistNode *header, *tail; //表头节点、表尾节点
unsigned long length; //表中节点的数量
int level; //表中层数最大的节点的层数
}zskiplist;
6、整数集合
整数集合(intset)是redis用于保存整数值的集合抽象数据结构,它可以保存的类型为:
int16_t、int32_t、int64_t的整数值;
SADD numbers 1 2 3 4 5
OBJECT ENCODING numbers
typedef struct intset{
uint32_t encoding; //编码方式int16_t、int32_t、int64_t
uint32_t length; //集合包含的元素数量
int8_t contents[]; //保存元素的数组
}intset;
升级:从int16_t...升级至int64_t,且不能降级;
7、压缩列表
压缩列表是列表键和哈希键的底层实现之一;
RPUSH lst 1 3 5 10086 "hello" "world"
OBJECT ENCODING lst
压缩列表的构成
zlbytes zltail zllen entry1 entry2 ... entryN zlend
8、对象
Redis的主要数据结构:简单动态字符串SDS、双端链表、字典、跳跃表、整数集合、压缩列表;
Redis包含的对象:字符串对象、列表对象、哈希对象、有序集合对象、集合对象;
Redis中的每个对象都由一个redisObject结构表示,该结构中和保存数据有关的三个属性分别是type、encoding、ptr:
typedef struct redisObject{
unsigned type:4; //类型
unsigned encoding:4; //编码;
void *ptr; //指向底层实现数据结构的指针;
}
类型常量/对象名称:REDIT_STRING/字符串对象、REDIS_LIST/列表对象、REDIS_HASH/哈希对象、
REDIS_SET/集合对象、REDIS_ZSET/有序集合对象;
SET msg "hello world"
TYPE msg
返回:string
OBJECT ENCODING
返回:embstr
编码和底层实现
编码常量 编码所对应的底层数据结构
REDIS_ENCODING_INT long类型的整数
REDIS_ENCODING_EMBSTR 编码的简单动态字符串
REDIS_ENCODING_RAW 简单动态字符串
REDIS_ENCODING_HT 字典
REDIS_ENCODING_LINKEDLIST 双端链表
REDIS_ENCODING_ZIPLIST 压缩列表
REDIS_ENCODING_INTSET 整数集合
REDIS_ENCODING_SKIPLIST 跳跃表和字典
不同类型和编码对象
类型/TYPE 编码/OBJECT ENCODING 对象
REDIS_STRING REDIS_ENCODING_INT 整数值实现的字符串对象
REDIS_STRING REDIS_ENCODING_EMBSTR embstr编码的简单动态字符串实现的字符串对象
REDIS_STRING REDIS_ENCODING_RAW 简单动态字符串实现的字符串对象
REDIS_LIST REDIS_ENCODING_ZIPLIST 压缩列表实现的列表对象
REDIS_LIST REDIS_ENCODING_LINKEDLIST 双端链表实现的列表对象
REDIS_HASH REDIS_ENCODING_ZIPLIST 压缩列表实现的哈希对象  
REDIS_HASH REDIS_ENCODING_HT 字典实现的哈希对象  
REDIS_SET REDIS_ENCODING_INTSET 整数集合实现的集合对象
REDIS_SET REDIS_ENCODING_HT 字典实现的集合对象
REDIS_ZSET REDIS_ENCODING_ZIPLIST 压缩列表实现的有序集合对象
REDIS_ZSET REDIS_ENCODING_SKIPLIST 跳跃表和字典实现的有序集合对象
字符串对象,编码可以是int、embstr、raw;
int:如果字符串对象保存的是整数值,且可以用long类型来表示,那么编码为int;
embstr:如果字符串对象保存的是一个字符串值,并且这个字符串值的长度<=39字节,那么编码为embstr;
raw:如果字符串对象保存的是一个字符串值,并且这个字符串值的长度>39字节,那么用一个SDS保存,且编码为raw;
embstr:两个连续的内存空间,raw两个分开的内存空间;
字符串的命令实现:
SET:赋值;
GET:取值;
APPEND:后缀字符串;
INCRBYFLOAT:double相加;
INCRBY:int相加;
DECRBY:int相减;
STRLEN:返回字符串的长度;
SETRANGE:将字符串指定索引上的值设置为给定的字符;
GETRANGE:取指定索引的字符;
列表对象
列表对象的编码可以是ziplist或者linkedlist;
RPUSH numbers1 "three" 5
同时满足以下两个条件,列表对象使用ziplist编码:其他条件下用linkedlist编码;
1)列表对象保存的所有字符串元素的长度都小于64字节;
2)列表对象保存的元素数量小于512个;
列表命令的实现:
LPUSH:将新元素压入表头;
RPUSH:将新元素压入表尾;
LPOP:返回表头节点并删除;
RPOP:返回表尾节点并删除;
LINDEX:返回指定索引的节点;
LLEN:返回列表长度;
LINSERT:将新节点插入指定索引位置;
LREM:删除指定节点;
LTRIM:删除不在指定索引范围的元素;
LSET:覆盖指定索引元素;
哈希对象
哈希对象的编码可以是ziplist或者hashtable;
HSET book name "thinking in java"
同时满足以下两个条件,哈希对象使用ziplist编码:其他条件下用hashtable编码;
1)哈希对象保存的所有键值对的键和值的字符串长度都小于64字节;
2)哈希对象保存的键值对数量小于512个;
哈希命令的实现:
HSET:新增元素;
HGET:取值;
HEXISTS:查找指定的键;
HDEL:删除元素;
HLEN:求长度;
HGETALL:返回所有的键值对;
集合对象:不能有重复的值;
集合对象的编码可以是intset或者hashtable;
当集合对象同时满足以下两个条件时,对象使用intset编码,其他条件使用hashtable编码;
1)集合对象保存的所有元素都是整数值;
2)集合对象保存的元素数量不超过512个;
结合命令的实现:
SADD:新增元素;
SCARD:返回集合的元素数量;
SISMEMBER:查找是否存在指定元素;
SMEMBERS:返回所有集合元素;
SRANDMEMBER:随机返回一个元素;
SPOP:随机取一个元素返回,并删除;
SREM:删除给定的元素;
有序集合对象
有序集合对象的编码可以是ziplist或者skiplist;
ZADD price 8.5 apple 5.0 banana 6.0,数字是排序因子,从小到大排;
当有序集合对象可以同时满足以下两个条件时,对象使用ziplist编码,其他条件skiplist编码;
1)元素数量小于128个;
2)元素成员长度<64字节;
有序集合的命令实现:
ZADD:添加元素;
ZCARD:返回集合元素数量;
ZCOUNT:统计分值在给定范围的元素数量;
ZRANGE:从表头遍历,返回给定索引范围的元素;
ZREVRANGE:从表尾遍历,返回给定索引范围的元素;
ZRANK:从表头遍历,返回给定元素的索引;
ZREVRANK:从表尾遍历,返回给定元素的索引;
ZREM:删除指定定的元素;
ZSCORE:返回指定元素的分值;
可以对任何类型的键执行:DEL、EXPIRE、RENAME、TYPE、OBJECT;
9、数据库
typedef struct redisServer{
redisDb *DB; //一个数组,保存着服务器中的所有数据库
}redisServer;
typedef struct redisDb{
dict *dict; //数据库键空间,保存着数据库中的所有键值对
}redisDb;
每个键都是一个字符串对象;
切换数据库:默认为0号数据库;
SELECT 2
添加新键:SET date '2014-03-12'
删除键:DEL date
更新键:SET date '2014-03-13'
取值:GET date
设置键的生存时间或过期时间
EXPIRE、PEXPIRE:经过多少秒/毫秒后删除键;
EXPIREAT、PEXPIREAT:设置秒/毫秒时间戳;
TTL、PTTL:返回键的剩余生存时间;
EXPIRE key 1000;
移除过期
PERSIST:移除一个键的过期时间;
过期键的删除策略
定时删除:在设置键的过期时间的同时,创建一个定时期,当过期时间到来时,删除键;
惰性删除:每次取键时,看该键有没有过期,如果过期则删除;如果没有过期,则返回;
定期删除:每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键;
AOF、RDB、复制功能对过期键的处理
生成RDB文件
在执行SAVE或者BGSAVE命令创建一个新的RDB文件时,程序会对数据库中的键进行检查,已过期的键不会被保存到新创建的RDB文件中;
载入RDB文件
在启动Redis服务器时,如果服务器开启了RDB功能,那么服务器将对RDB文件进行载入:
如果服务器以主服务器模式运行,那么在载入RDB文件时,程序会对文件中保存的键进行检查,未过期的键会被载入到数据库中,
而过期键会被忽略;
如果服务器以从服务器模式运行,那么在载入RDB文件时,文件中保存的所有键,不论是否过期,都会被载入到数据库中;
因为主从服务器在进行数据同步时,从服务器的数据库就会被清空,所以一般来讲,过期键对载入RDB文件的从服务器
也不会造成影响;
AOF文件写入
当服务器以AOF持久化模式运行时,如果数据库中的某个键已经过期,但他还没有被惰性删除或者定期删除,
那么AOF文件不会因为这个过期键而产生任何影响;
当过期键被惰性删除或定期删除后,程序会向AOF文件追加一条DEL命令,来显式地记录该键已被删除。
AOF重写
在执行AOF重写的过程中,程序会对数据库中的键进行检查,已过期的键不会被保存到重写后的AOF文件中;
复制
当服务器运行在复制模式下时,从服务器的过期键删除动作由主服务器控制:
主服务器在删除一个过期键之后,会显式地向所有从服务器发送一个DEL命令,告知从服务器删除这个过期键;
从服务器在执行客户端发送的命令时,即使碰到过期键也不会将过期键删除,而是继续像处理未过期的键一样
来处理过期键;
从服务器只有在接到主服务器发来的DEL命令后,才会删除过期键;
如果客户端向从服务器发送命令GET message,那么从服务器将发贤message键已经过期,但从服务器并不会删除
message键,而是继续将message键的值返回给客户端,好像message键并没有过期一样。
如果客户端向主服务器发送命令GET message,那么主服务器发贤键message已经过期,主服务器会删除message键,
向客户端返回空回复,并向从服务器发送DEL message命令;
10、RDB持久化
SAVE、BGSAVE:生成RDB文件;
SAVE命令会阻塞Redis服务器进程,直到RDB文件创建完毕;在服务器进程阻塞期间,服务器不能处理任何命令请求;
BGSAVE命令会派生出一个子进程,然后由子进程负责创建RDB文件,服务器进程(父进程)继续处理命令请求;
服务器在载入RDB文件期间,会一直处于阻塞状态,直到载入工作完成为止;
因为AOF文件的更新频率通常比RDB文件的更新频率高,所以:
如果服务器开启了AOF持久化功能,那么服务器会优先使用AOF文件来还原数据库状态;
只有在AOF持久化功能处于关闭状态时,服务器才会使用RDB文件来还原数据库状态;
自动间隔性保存
通过配置save选项,让服务器每隔一段时间自动执行一次BGSAVE命令;
save 900 1 //900秒内,对数据库至少执行了一次修改
save 300 10
save 60 10000
满足其中任意一个条件即可;
RDB文件结构
REDIS db_version databases EOF(表示内容结束) check_sum(校验和)
11、AOF持久化:通过保存Redis服务器执行的写命令来记录数据库状态;
AOF持久化功能的实现分为命令追加、文件写入、文件同步三个步骤;
命令追加:服务器在执行完一个写命令后,会以协议格式将被执行的写命令追加到服务器状态的aof_buf缓冲区的末尾;
AOF文件的写入与同步:将缓冲区的命令执行写入Redis,并同步到AOF文件中;
AOF重写:新建一个AOF文件,把数据库的当前状态同步到新的AOF文件中;
AOF重写缓冲区;在重写时产生的新的写命令会同时保存到AOF重写缓冲区,执行完重写后,把重写缓冲区的命令写入AOF;
12、事件
文件事件:Redis服务器通过套接字与客户端进行连接,而文件事件就是服务器对套接字操作的抽象。
服务器与客户端的通信会产生相应的文件事件,而服务器则通过监听并处理这些事件来完成一系列网络通信操作;
时间事件:Redis服务器中的一些操作需要在给定的时间点执行,而时间事件就是服务器对这类定时操作的抽象;
Redis通信:I/O多路复用;
13、客户端
CLIENT list:目前所有连接到服务器的客户端;
默认情况下,一个连接到服务器的客户端是没有名字的;
CLIENT setname命令可以给客户端设置一个名字;
14、服务器
15、复制
通过SLAVEOF命令或设置slaveof选项,让一个服务器去复制另一个服务器,被复制的服务器为主服务器,复制的服务器为从服务器;
127.0.0.1:12345> SLAVEOF 127.0.0.1 6379
6379是主服务器;12345是从服务器;
复制功能的实现
旧:
同步:发送SYNC命令,主服务器生成一个全量的RDB文件,发送给从服务器;
命令传播:主服务器执行了写命令,会立即发送给从服务器;
新:
同步:增量的命令发送给从服务器;
19、事务
Redis通过MULTI、EXEC、WATCH等命令来实现事务功能;
事务提供了一种将多个命令请求打包,然后一次性、按顺序地执行多个命令的机制;
并且在事务执行期间,服务器不会中断事务而改去执行其他客户端的命令请求,
它会将事务中的所有命令都执行完毕,然后才去处理其他客户端的命令请求;
MULTI
SET "name" "value"
SET "name2" "value2"
EXEC
1、事务开始;2、命令入队;3、事务执行;
WATCH命令是一个乐观锁,它可以在EXEC命令执行之前,件事任意数量的数据库键,并在执行EXEC命令执行时,
检查被监视的键是否至少有一个已经被修改过了,如果是的话,服务器将拒绝执行事务,并向客户端返回
代表事务执行失败的空回复。
WATCH "name"
MULTI
SET "name" "value"
EXEC
事务的ACID性质
Redis不提供回滚功能,执行错误了不影响已经执行的命令和接下来要执行的命令;
21、排序:默认升序
Redis的SORT命令可以对列表键、集合键或者有序集合键的值进行排序。
SORT numbers,会对一个包含数字值的键key进行排序;
SORT strs ALPHA
通过ALPHA,SORT命令可以对包含字符串值的键进行排序;
SORT numbers ASC/DESC
BY
SADD fruits "apple" "banana" "cherry"
MSET apple-price 8 banana-price 5.5 cherry-price 7
SORT fruits BY *-price [ALPHA]
LIMIT
SORT命令默认返回所有的值,LIMIT可以限制
SORT fruits ALPHA LIMIT 0 4 //返回4个值;
GET选项
STORE:保存排序结果
SORT students ALPHA STORE sorted_students
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值