Redis系统学习-原理

redis为什么快

1.单线程-没有cpu上下文切换的开销。
2.所有数据都在内存中,所有的运算都是内存级别的。(cpu频率一致)
3.采用多路复用的方式,处理多并发客户端连接。

IO模型

和java的NIO一样*
http://www.importnew.com/22623.html
https://blog.csdn.net/u011381576/article/details/79876754

通信协议

使用可读性很强,但是大量出现\r\n的文本序列化协议,(典型i性能换可读性案例)
1、单行字符串 以 + 符号开头。
2、多行字符串 以 $ 符号开头,后跟字符串长度。
3、整数值 以 : 符号开头,后跟整数的字符串形式。
4、错误消息 以 - 符号开头。
5、数组 以 * 号开头,后跟数组的长度。

基于netty的设计:https://juejin.im/post/5aaf1e0af265da2381556c0e

持久化

数据放在内存的必然问题,Redis 的持久化机制有两种,第一种是快照,第二种是 AOF 日志。快照是一次全量备份,AOF 日志是连续的增量备份。快照是内存数据的二进制序列化形式,在存储上非常紧凑,而 AOF 日志记录的是内存数据修改的指令记录文本。AOF 日志在长期的运行过程中会变的无比庞大,数据库重启时需要加载 AOF 日志进行指令重放,这个时间就会无比漫长。所以需要定期进行 AOF 重写,给 AOF 日志进行瘦身。

Redis 使用操作系统的多进程 COW(Copy On Write) 机制来实现快照持久化,这个机制很有意思,也很少人知道。多进程 COW 也是鉴定程序员知识广度的一个重要指标

Redis 在持久化时会调用 glibc 的函数fork产生一个子进程,快照持久化完全交给子进程来处理,父进程继续处理客户端请求。子进程刚刚产生时,它和父进程共享内存里面的代码段和数据段。这时你可以将父子进程想像成一个连体婴儿,共享身体。这是 Linux 操作系统的机制,为了节约内存资源,所以尽可能让它们共享起来。在进程分离的一瞬间,内存的增长几乎没有明显变化

管道

管道不是redis独特有的技术,并且管道不是redis服务端的技术,是客户端想让自己的链接更有作用,提出了管道复用链接。
说白了,就是一次性可以执行多条命令,一般面试官会问redis单节点一次请求量很大,这种怎么处理?产生了很多的链接怎么办?
本质原理很复杂,还没到深入的时候,后期再看。
客户端通过改变了读写的顺序带来的性能的巨大提升。

事务

multi/exec/discard。multi 指示事务的开始,exec 指示事务的执行,discard 指示事务的丢弃。

multi
OK
incr books
QUEUED
incr books
QUEUED
exec
(integer) 1
(integer) 2
所有的指令在 exec 之前不执行,而是缓存在服务器的一个事务队列中,服务器一旦收到 exec 指令,才开执行整个事务队列,执行完毕后一次性返回所有指令的运行结果。因为 Redis 的单线程特性,它不用担心自己在执行队列的时候被其它指令打搅,可以保证他们能得到的「原子性」执行。

redis的事务不是真正的事务,事务中间发生错误,错误之前的操作都会生效,这里只是实现了事务的隔离性。
discard 需要在exec 之前执行,就是清空指令队列。
说到指令队列,很容易想到上面的管道,所以,一般事务都是结合管道来的。

Watch
我们一般用到redis的分布式锁,都是悲观锁,获取不到就不执行了。
Redis 提供了这种 watch 的机制,它就是一种乐观锁。有了 watch 我们又多了一种可以用来解决并发修改的方法。

watch 会在事务开始之前盯住 1 个或多个关键变量,当事务执行时,也就是服务器收到了 exec 指令要顺序执行缓存的事务队列时,Redis 会检查关键变量自 watch 之后,是否被修改了 (包括当前事务所在的客户端)。如果关键变量被人动过了,exec 指令就会返回 null 回复告知客户端事务执行失败,这个时候客户端一般会选择重试

注意事项
Redis 禁止在 multi 和 exec 之间执行 watch 指令,而必须在 multi 之前做好盯住关键变量,否则会出错。

为什么不支持事务回滚:
只有当发生语法错误(这个问题在命令队列时无法检测到)了,Redis命令才会执行失败, 或对keys赋予了一个类型错误的数据:这意味着这些都是程序性错误,这类错误在开发的过程中就能够发现并解决掉,几乎不会出现在生产环境。
由于不需要回滚,这使得Redis内部更加简单,而且运行速度更快。

PubSub(PublisherSubscriber)

利用redis的list数据结构特性,可以当作异步消息队列使用,但是不足之处就是支持广播。pubSub可以了。

消息多播 - 允许生产者生产一次消息,中间件负责将消息复制到多个消息队列,每个消息队列由相应的消费组进行消费。它是分布式系统常用的一种解耦方式,用于将多个消费组的逻辑进行拆分。支持了消息多播,多个消费组的逻辑就可以放到不同的子系统中。
如果是普通的消息队列,就得将多个不同的消费组逻辑串接起来放在一个子系统中,进行连续消费。
PubSub 的消费者如果使用休眠的方式来轮询消息,也会遭遇消息处理不及时的问题。不过我们可以使用 listen 来阻塞监听消息来进行处理,这点同 blpop 原理是一样的。
但是没有中间缓存机制,很少又场景用到这个,近期 Redis5.0 新增了 Stream 数据结构,这个功能给 Redis 带来了持久化消息队列。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值