没用过,随便写写看看。
1.redis高性能的原因
2.redis的持久化
1.单线程和多路复用
1.1单线程
redis的服务端采用的是单线程处理用户请求。那为什么会这么设计
1.简单,肯定比多线程简单了
2.CPU不是瓶颈,真正的瓶颈是内存大小和网络开销。所以没必要。
如果我有多个CPU怎么{BANNED}{BANNED}最佳佳大限度利用。
简单,多开几个进程就可以了。
1.2 IO多路复用
可以看看我之前写的非阻塞式IO,其实原理是一模一样的。熟悉linux C语言同学应该知道linux提供了select函数。具体代码可以看看JAVA NIO的技术。这里只介绍思想和理论。
在LINUX定义里面,一切可以产生和消费消息的东西都是文件,以此类推,网络套接字SOCKET肯定也是文件。
在REDIS上,一个服务端,肯定是同时在服务多个服务端的。有2种办法
方法1:给每一个客户端创建一个线程,然后一线程负责一个。很麻烦,但也挺高效,但对此也会带来很多问题,比如共享资源问题。
方法2:一个线程服务所有客户端。然后这个线程开始一个一个去服务,先服务完A,再去服务B,再去服务C,等等。
明显方法1不是redis的菜,刚才说过redis是单线程。
方法2可以用,但很慢。先分析慢的原因:CPU我们知道是很快的,内存也很快,谁慢,肯定是网络慢。那么接下来的思想就是:服务器主线程在等通知,各个客户端的网络各自去准备吧,你们谁准备好了,通知一声,我就为准备好的SOCKET服务。具体代码 SELECT, POLL, EPOLL等。
2.持久化
redis用内存来保存数据,但有时我们会把他持久化下来,这样当redis挂了,或者重启什么的。能从磁盘上恢复缓存数据。一下介绍2种持久化的策略。
2.1 RDB
你可以理解其实就是全量备份,比如在某个时刻把内存里面所有的信息全部持久化下来。那么问题来了。假设你准备把00分00秒数据持久化,但数据很多,整个备份过程需要1个小时(夸张了点,不过无所谓)。那么这段时间内数据一直在变,你怎么保证在30分00秒时候保存下来的数据是00分00秒那个时刻的快照呢?
方法1:save 策略(同步,阻塞)这1个小时内,不允许写redis,可以达到目标。可以使用这种策略,但我理解大部分人不会开启这种策略,如果数据多,备份的时候整个redis的RT会非常高。
方法2:bgsave 策略(异步,非阻塞),这里讲到一个copy on write. 简单理解,当我要持久化时候,我创建一个备份线程,一旦创建了,我就把所有用来装数据的内存设置成只读,然后这个备份线程就开始慢慢去持久化吧。这个时候如果有人来写呢,就会触发只读异常,这个时候进入异常处理中,异常会把这戈数据页内容拷贝出来,然后去改。后面从客户端过来的读就读这个拷贝出来的数据。
一般可以设置RDB周期性执行。
2.2 AOF
其实就是增量备份,就是把所有写命令保存下来。如果挂了,就把写命令从新跑一遍,就恢复了。后面AOF的备份文件会很大。怎么优化呢,其实AOF备份保存了很多过程数据,我们只要结果数据就可以了。比如执行了3次写操作 SET K1 V1, SET K1 V2, SET K1 V3。其实我们只用保存{BANNED}最佳后一个命令。因此可以压缩。
实际情况下,一般是RDB和AOF结合起来用。
RDB一次性保存数据,再用AOF克服去丢数据的缺点。