另可参考:http://www.stevenwash.xin/2018/04/21/Redis%E5%9F%BA%E7%A1%80/
是一款基于内存的数据结构服务器,可以用作数据库(支持持久化)、高速缓存和消息队列。
1、相比memcache而言,支持的value类型更多,有:string、list、set、zset、hashs等
2、支持主从模式的数据备份
3、所有的操作都是原子性的
4、还支持publish/subscribe、通知、key过期等
网络模型:Redis使用单线程的IO复用模型,会影响整体吞吐量
内存管理:使用现场申请内存的方式来存储数据(相比memcache的预申请而言),会更容易产生内存碎片。
数据一致性:没有Memcache实现的好,Memcache提供了cas命令,可以保证多并发访问统一数据的一致性,Redis虽然没有cas,但是提供了事务的功能,可以保证一串命令的原子性。
两种方式:RDB和AOF
是通过快照的方式完成的,当符合某种规则的时候(save n1 n2),会将内存中的数据全量生成一份副本存储在硬盘上
会进行快照的情况:
1、根据配置规则
2、用户执行save或bgsave命令
3、执行flushall命令
4、执行复制的时候(此时会自动执行)
优点:
1、存储的是一个经过压缩之后的二进制文件,代表某个时间节点上的行数据快照。
2、Redis加载RDB文件要比加载AOF文件的速度快得多
缺点:
1、无法做到实时持久化,因为在执行bgsave的时候都会创建子进程来完成数据的保存,这个是重量级操作
2、由于采用二进制保存,在Redis的演进中又出现了多个版本的二进制格式,所以会出现老版本的Redis服务器不兼容新的RDB文件
是指Append Only File,是指对于存储非临时数据的时候,AOF会将Redis执行的每一条命令追加到硬盘中。
流程:
1、先将写入的命令写到AOF的缓冲区
2、将缓冲区中的数据同步到AOF文件中
3、随着AOF文件增大,对AOF文件进行重写
是以文本的形式存储,具有一定的可读性。
AOF对于一些无用的命令会进行重写,重写的方式也是通过创建子进程的方式来实现,只是增加了重写缓冲区
使用slaveof命令创建主从关系,使用slaveof no one断开主从关系。
复制过程:
1、slave启动时,向master发送同步信号
2、master接收到同步信号之后,开始进行RDB持久化,并将所有的写操作缓存,完成之后,将RDB文件和缓存起来的命令发给slave
3、slave收到之后就开始载入快照和命令,复制初始化完成
4、之后,每当master接收到写命令的时候,就会将命令同步给slave,这样就保证了主从一致
用于初次复制的场景,开销很大。
上面复制流程中的123步就是全量复制:RDB文件和缓存的命令
是针对全量复制高开销的优化手段。
复制偏移量:记录当前复制的位置,主从节点都会维护自身的复制偏移量,通过比较主从复制偏移量可以判断主从的节点上的数据是否是一致的。
复制积压缓冲区:在从节点创建之后,主节点响应写命令的时候,不但会吧命令发送给从节点,还会写入复制积压缓冲区,所以这个缓冲区中维护的就是一个最近已复制的数据,用于数据的补救。
部分复制流程(出现在主从复制过程中断开了连接,然后又重新连接上了的情况):
1、当主从之间的网络连接中断之后,超过一定的时间还没有的到相应,此时主节点和从节点都会进行复制中断的操作。
2、主从连接中断之后,主节点会继续响应写命令,然后将这些写命令缓存到复制积压缓冲区中。
3、当主从节点的连接恢复之后,从节点会再次连接上主节点。
4、在连接恢复之后,从节点会将之前自己保存的复制偏移量和主节点的id发给从节点,主节点收到之后会查看从节点发过来的id是不是自己的id,并且根据从节点的复制偏移量在复制积压缓冲区中查找,找到了从节点偏移量之后的数据,然后就发送CONTINUE的命令给从节点,告诉从节点可以开始复制了。
5、然后主节点就会将从节点偏移量之后的数据从复制解压缓冲区中取出来发给从节点,完成部分复制。
Special Note:主从节点之间建立复制之后,会建立长连接来维护心跳,主节点默认每隔10秒钟ping一下从节点,看从节点是否还活着,然后从节点每隔1秒钟就将自身的复制偏移量发给主节点。
也是采用上面介绍的节点取余、一致性哈希、虚拟槽分区来将数据集进行分布。
其中Redis Cluster采用的就是虚拟槽分区。
1、所有的集群的节点之间都是互联互通的
2、节点与节点之间通过二进制协议进行通信
3、客户端和节点之间的通信通过文本协议进行
4、集群节点不会代理查询
集群中的节点通过Gossip协议进行彼此之间的通信,来达到所有的节点之间都能互相感知的目的。
每当有新的节点加入到集群,握手的消息就会在集群内进行传播(类似流言)。
1、缓存
只需要将需要进行缓存的对象进行序列化,然后将序列化之后的内容放进Redis中即可。
需要注意的是:
1、要保证每个不同对象的key不会重复,并且key尽量短。
2、选择一个优秀的序列化的方式,提高序列化效率减少内存占用(protostuff)
保证一致性:(跟memcache相似)
1、只在数据查询后将数据放在缓存中
2、对数据进行修改之后要更新缓存的内容
2、消息队列
Redis中的list是用双向链表实现的,所以消息的生产者只需要通过lpush将消息放入到list中,然后消息的消费者通过lpop将消息取出来,这就可以保证了消息的有序性。也可以使用sorted set来实现带有优先级的消息队列。
加上Redis的持久化功能,不用担心消息的丢失。
3、时间轴
list作为双向链表还可以当做栈来使用,将完成的事件放到list中,按照栈的方式就可以的到最近完成的事情。
4、好友关系
通过set实现。能快速算出两个集合的交集。
假设一个用户A,将A用户关注的和关注A用户的id分别放在两个表中:
A:follow A:follower
此时只需要通过sinter的方法求出A:follow和A:follower两个集合的交集,得到的便是与A互相关注的人(即为好友关系)。
当A进入另一个用户B的主页之后,A:follow和B:follow的交集便是两者的共同关注,A:follow和B:follower便是A关注的也关注了B。
1、性能上
Redis使用的是单核,Memcache可以使用多核,所以在每一核上存储小数据的时候,Redis会更好。但是在100k以上的数据中,Memcache的性能要高于Redis。
2、内存空间上
Memcache可以修改最大内存数,是使用预申请的方式先申请内存,不容易产生内存碎片,但是会导致内存浪费,并且采用LRU算法将最近最少使用的缓存进行清除。
Redis是运行时申请内存,但是会更容易产生内存碎片,增加了VM的特性,突破了物理内存的限制。
3、操作便利上
Memcache简单,数据类型单一,仅用来做缓存。
Redis支持的数据类型更加复杂多样,也可以在服务端直接对数据进行操作,可以用作缓存和数据库。
4、可靠性
Memcache不支持数据持久化,断电或重启之后数据就会丢失。
Redis支持数据的持久化和数据恢复,允许单点故障,但是会付出性能单价
5、应用场景
Memcache减轻数据库负载,做缓存,适合多读少写,大量数据的情况
Redis适用于对读写效率要求都很高的情况,数据的处理业务复杂以及对安全性的要求较高的系统
Special: Ehcache 也是告诉缓存,是用在JVM内部,速度快、效率高,但是在集群中使用起来不方便。