《redis设计与实现》读书笔记

redis , nosql。
默认port:6379
性能非常高,15W左右的qps。C语言写的。
通常适合做缓存,也可以持久化。
是完全开源的、高性能的分布式内存数据库,基于内存且支持持久化的数据库。
(支持hash、list、set、string、sorted set)
支持数据备份,master-slave模式的数据备份。
redis的所有操作都是原子性的,(要么成功要么不成功)。单个操作是原子性,多个操作也支持事物。
丰富的特性(如key过期)。
HyperLogLog:PFADD key "VALUE"
给key加上很多value,通过PFCOUNT来计算出基数
单线程,内存跑,CPU不是瓶颈,单线程串行避免了许多问题。
http://try.redis.io  可以尝试使用redis

原理:
程序发请求给-》redis的监听组件,redis解析指令,操作。

redis的数据结构使用起来比编程语言更高效,redis的github上如此描述。
set key value
RPUSH key value1 value2 value3
表示创建一个value是[value1,value2,value3]的list对象
get key //这样可以获得结果
dbsize	//查看数据库的key-value个数
mset a 123 b 456 c 789 //批量赋值
默认15个数据库。下标从0开始。
通过select [number]	//来进行数据库的切换
flushdb  清空数据库。
redis:
简单字符串SDS:
struct sdshdr{
	int len,free; //len表示字符串的长度,free表示数组未使用字节的数量
    char buff[]; //字符串不定长有可能,缓冲区溢出
}

list:
struct listNode{
	struct listNode *next;
    struct listNode *next;
    void *value;
};
dict,hash实现。
redis的sorted 有序集合键,跳表。
平均O(logN),最坏O(N)

set a 123
expire a 123 //espire=set+123s后失效
hmset a 123 456 789  //设置的hash

过期删除策略:定期、定时、惰性(对cpu友好,对内存不友好,内存泄漏)

跳表:
由很多个表组成,一个表由很多层元素组成(这些元素)
有序数组,使用的跳表:https://www.jianshu.com/p/61f8cad04177
一张图看明白。
跳跃表 level 层级完全是随机的。一般来说,层级越多,访问节点的速度越快。
插入一个结点就在对应的地方加上这个值。
删除即为链表的删除。
查询的时候,从第一层开始查找,找到如果下一个比它大,那么它就下移。

redis对象:
redis基于一些数据结构,生成了一个对象系统,这个系统包含(字符串、列表、hash、有序数组、集合对象等)。
使用对象的好处,可以针对不同的使用场景为对象设置不同的数据结构,使得在不同场景下进行优化。
redis采用引用计数法的方式回收内存,并且通过指针实现了对象共享机制。

redis:

关于redis数据库。
Redis服务器将所有数据库都保存在redis.h/redisServer结构的db。
初始化服务器时,会根据dbnum属性来决定创建多少个数据库。

通过修改redisClient.db指针,让它们指向服务器的不同数据库,从而实现切换数据库的目的。
Rpush key value
//插入key这个链表中value。

这里google是一个域
redis 127.0.0.1:6379> HSET website google "www.g.cn"      # 设置一个新域
redis 127.0.0.1:6379>HSET website google "www.google.com" # 覆盖一个旧域

相当于,这里key为website。 然后google为被hash的key "www.g.cn" 为value

基本语句对应的数据结构:

data structure:

redis在读写过程中存在的操作:
1、记录每次缓存是否命中。
2、读取一个键后,计算LRU。
3、在读取一个键后,如果发现已过期,那么服务器会先删除这个键。
TTL key //获取一个key的剩余存活时间

使用RDB:
(会判断这个键是否存活,死掉的键不会生成RDB文件)
启动redis服务器时,如果服务器开启了RDB功能,那么服务器对RDB文件进行载入:
(如果是主服务器,在载入RDB文件时,程序会对文件中保存的键进行检查,过期的键会被忽略)
(如果是从服务器,在载入RDB文件时,会全部载入,因为在主数据库同步的时候,从数据库会对应同步)

redis的两种可持久化方式(RDB/AOF持久化)
RDB(redis database)做法:
在不同的时间点,将redis存储的数据生成快照并存储
具体:fork一个子进程做持久化,不影响主进程的I/O,保持高速。
比如每5分钟保存一次快照,那么数据的完整性不是那么高(redis故障时,存在5分钟的数据丢失)
,生成RDB文件。
(其中RDB是个被压缩的二进制文件)

AOF(append of file)做法:
增量的方式,记录(如SET、SADD、RPUSH等)的语句,比如每秒钟的写操作。
当删除的时候,也会增量追加DEL在文件后面。

different:
1、RDB全量,AOF增量保存。
2、RDB数据完整性不是那么好,AOF的数据完整性好一些。
3、RDB数据还原速度块,毕竟是快照。AOF还原速度慢,
4、RDB体积重,AOF体积轻。
5、 RDB的fork() 可能会非常耗时,造成服务器在某某毫秒内停止处理客户端

场景:
1、RDB适用于备份、容灾,数据完整性要求不是非常高。
2、RDB的保存快照的时间会稍微 长一些。
3、AOF可以每s一次保存增量,其cpu消耗量比较低。

持久化具体做法:SAVE、BGSAVE。
其中SAVE会直接阻塞,直至RDB文件创建结束,而BGSAVE会创建子进程做这个操作。
redis没有载入命令,是在redis启动的时候检测是否载入(这里需要配置)

AOF文件的更新频率比较高,所以在恢复的时候,默认首先选择AOF

AOF持久化的效率和安全性:
1、appendfsync的值为always时,表示只要有内容,就放到buff,并且同步到磁盘。
2、值为everysec时候,会每秒钟进行同步。
3、为no时,只保存在buffer中,由os控制何时存入磁盘。

AOF如果一直增量存,会出现文件过大,此时有个叫“AOF重写的功能”
AOF重写:把redis中所有键值保存下来(用RPUSH来替代,那么新的AOF文件就没有冗余了)

自动间歇性保存:
save 900 10 //服务器在900s中有10次操作,就进行保存

dirty//从上次SAVE到现在,有了多少次修改。
lastsave//上次修改的时间是什么时候。

redis cluster:

redis的主从问题:
主服务器同步写操作给从服务器时,才会删除过期键。
会出现《读》从服务器时,过期的键仍然返回有效的结果。

Reactor(反应器模式):
1、一个请求,创建一个进程来处理。(被阻塞后,影响后续)
2、对每一个请求,建立一个对应的线程来处理,
(过度的创建与切换线程的资源消费过大,并且长连接一只保存创建,消费资源较大)。
3、就是一个reactor(反应堆)进行监听,把监听的结果返回给各个资源中。
4、reactor的好处在于,在请求发出后,这个reactor不需要阻塞,
基本步骤:
1、创建一个reactor管理器。
2、设置事件与回调函数。
3、发生事件,对事件进行注册。
4、进入循环,并等待事件发生并处理。
Reactor应用于同步I/O.
Proactor.

redis服务器是事件驱动程序:
1、文件事件(file event)。时间事件(time event)
2、redis基于Reactor模式

redis cluster:
如何构建成集群?
CLUSTER MEET <ip> <port>  //构建一个redis cluster集群。
CLUSTER NODE //查看redis集群
redis需要自己设置(cluster-enabled配置选项是否为yes来决定是否开启集群模式)

集群节点保存的信息:
1、clusterNode记录节点的当前状态,节点的创建时间、节点的名字、节点的ip地址与端口号。
2、每个节点都会用一个clusterNode记录自己的信息,并为其他节点建立相应的clusterNode。
3、clusterState记录当前节点的视角下,集群目前的状态,集群包含多少个节点,集群当前的配置纪元等等。

创建的逻辑:
1、节点A向节点B创建一个clusterNode结构,并将这个结构添加到自己的字典里面。
2、然后A向B发送一个MEET消息,B收到后,把A加入到自己的clusterState.nodes字典中。
3、然后,节点B向节点A发送一条PONG信息,表示自己接收到了这条信息。
4、此时节点A向B发送一个信息PING,表示自己接收到了PONG,握手完成。

redis集群通过分片,分成了16384个槽(slot)。
127.0.0.1:7000 =》 CLUSTER ADDSLOTS 1,2,3 把槽1/2/3给节点7000使用

//当数据库中的16384个槽都有节点在处理时,集群处于上线状态(ok)
//相反,如果数据库中有任何一个槽没有得到处理,那么集群处于下线状态(fail)。
O(1)查找某节点是否被指派/指派给了谁。
CLUSTER KEYSLOT "msg" 计算"msg"属于哪个槽
每个键属于一个槽

集群模式下:
redis-cli客户端在接收到MOVED错误时,不会打印出MOVED错误,而是根据MOVED错误自动进行节点转向。
但是当选择(stand alone)单机模式,就会报这个错误。

判断自身是否负责某节点。

节点同步:

如何存一个节点指派给了谁:

集群通信判断节点。

集群模式下:
redis-cli客户端在接收到MOVED错误时,不会打印出MOVED错误,而是根据MOVED错误自动进行节点转向。
但是当选择(stand alone)单机模式,就会报这个错误。

键值迁移:

订阅模式:

也就是client可以收到服务器的通知

 

redis事务

将多个命令进行打包,然后一次性,按顺序执行。
事物的目的:
解决并发环境下,数据一致性的问题。
两个cpu,对一个数据进行操作,希望结果一致。

redis支持lua脚本。(lua是一个轻量级脚本语言)

monitor(监视器):

redis的shell中 输入monitor
把这台服务器变成monitor。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值