由上述三个问题,看看redis如何解决这三大难题:node
Redis支持两种方式的持久化,一种是RDB方式、另外一种是AOF(append-only-file)方式。前者会根据指定的规则“定时”将内存中的数据存储在硬盘上,然后者每次会将事务操做记录下来。两种持久化方式能够单独使用其中一种,也能够将这两种方式结合使用。mysql
从对比中看看RDB和AOF的持久化的方式:redis
RDB方式 后台建立(fork)一个子进程去持久化数据,能够理解成磁盘和内存直接的一个读写IO,这个过程咱们会考虑三个问题:算法
AOF方式 默认状况下Redis没有开启AOF(append only file)方式的持久化,能够经过appendonly参数启用,在redis.conf中找到 appendonly yes.开启AOF持久化后每执行一条会更改Redis中的数据的命令后,Redis就会将该命令写入硬盘中的AOF文件。AOF文件的保存位置和RDB文件的位置相同,都是经过dir参数设置的,默认的文件名是apendonly.aof. 能够在redis.conf中的属性 appendfilename appendonlyh.aof修改.sql
AOF过程当中咱们已经明白的一点是:他的持久化并不是储存的是数据,而是记录,有点相似于mysql的binlog.因此AOF就算宕机也是不可能发生数据丢失的。那对于日志文件愈来愈大,AOF该如何处理?缓存
set foo 1 set foo 2 set foo 3 get 对于AOF的这份日志,其实最终只须要一个set foo 3.因此对于redis的aof文件能够配置重写策略,这个条件的配置为 auto-aof-rewritepercentage 100 auto-aof-rewrite-min-size 64mb服务器
auto-aof-rewrite-percentage 表示的是当目前的AOF文件大小超过上一次重写时的AOF文件大小的百分之多少时会再次进行重写,若是以前没有重写过,则以启动时AOF文件大小为依据网络
auto-aof-rewrite-min-size 表示限制了容许重写的最小AOF文件大小,一般在AOF文件很小的状况下即便其中有不少冗余的命令咱们也并不太关心。并发
AOF重写原理:app
aof的重写原理能够解决不阻塞的状况下保证数据的完整性。 重写的流程是这样,主进程会fork一个子进程出来进行AOF重写,这个重写过程并非基于原有的aof文件来作的,而是有点相似于快照的方式,全量遍历内存中的数据,而后逐个序列到aof文件中。在fork子进程这个过程当中,服务端仍然能够对外提供服务,那这个时候重写的aof文件的数据和redis内存数据不一致了怎么办?不用担忧,这个过程当中,主进程的数据更新操做,会缓存到aof_rewrite_buf中,也就是单独开辟一块缓存来存储重写期间收到的命令,当子进程重写完之后再把缓存中的数据追加到新的aof文件。当全部的数据所有追加到新的aof文件中后,把新的aof文件重命名为,此后全部的操做都会被写入新的aof文件。
Redis中提供了多种内存回收策略,当内存容量不足时,为了保证程序的运行,这时就不得不淘汰内存中的一些对象,释放这些对象占用的空间,那么选择淘汰哪些对象呢?
过时时间设置
在Redis中提供了Expire命令设置一个键的过时时间,到期之后Redis会自动删除它。这个在咱们实际使用过程当中用得很是多。 EXPIRE命令的使用方法为 EXPIRE key seconds 其中seconds 参数表示键的过时时间,单位为秒。其中可使用TTL key 查看时间剩余。
过时key自动删除的原理:
redis有两种方式去删除key:
消极方法(passive way) 在key被访问时若是发现它已经失效,那么就删除它.
积极方法(active way) 周期性地从设置了失效时间的主键中选择一部分失效的key删除 对于那些从未被查询的key,即使它们已通过期,被动方式也没法清除。所以Redis会周期性地随机测试一些key,已过时的key将会被删掉。Redis每秒会进行10次操做,具体的流程:
官方的解释是,CPU并非Redis的瓶颈所在,Redis的瓶颈主要在机器的内存和网络的带宽。那么Redis能不能处理高并发请求呢?固然是能够的,至于怎么实现的,目前只说一个名词:多路复用,至于什么事多路复用,在后续的netty框架博客中会详细介绍。
1. 主从复制
配置:
配置步骤很简单,例如如今有3台机器(master,node1,node2)
只须要在node1,node2的redis.conf 文件下加上一个slaveof master port。
错误排查:如何未成功,先检验node1和node2是否能够链接master的服务。
redis-cli -h master的iP -p 端口port
观察redis服务端状态的命令:127.0.0.1:6379> INFO replication
能够用来查看主从是否配置成功。
主从复制的特色:
master机器能够读写,slave机器默认状况下不能够写操做
主从复制,数据同步过程和原理:
slave 刚启动成为master的从库:
观察输出日志:
[2603] 18 Jan 10:32:41.106 * Slave asks for synchronization
[2603] 18 Jan 10:32:41.106 * Full resync requested by slave.
[2603] 18 Jan 10:32:41.106 * Starting BGSAVE for SYNC
[2603] 18 Jan 10:32:41.210 * Background saving started by pid 2618
[2618] 18 Jan 10:32:41.232 * DB saved on disk
[2618] 18 Jan 10:32:41.232 * RDB: 6 MB of memory used by copy-on-write
[2603] 18 Jan 10:32:41.333 * Background saving terminated with success
[2603] 18 Jan 10:32:41.333 * Synchronization with slave succeeded
复制代码
从日志能够看出,redis会触发bgsave去生成一个快照,而后发送给slave。从库load快照文件,成功而后通知主库。接下来会进行,增量复制从redis2.8开始,就支持主从复制的断点续传,若是主从复制过程当中,网络链接断掉了,那么能够接着上次复制的地方,继续复制下去,而不是从头开始复制一份masternode会在内存中建立一个backlog,master和slave都会保存一个replica offset还有一个masterid,offset就是保存在backlog中的。若是master和slave网络链接断掉了,slave会让master从上次的replicat offset开始继续复制可是若是没有找到对应的offset,那么就会执行一次全量同步。
另外一种复制方式就是无磁盘复制: Redis复制的工做原理基于RDB方式的持久化实现的,也就是master在后台保存RDB快照,slave接收到rdb文件并载入,可是这种方式会存在一些问题
经过如下配置来开启该功能 repl-diskless-sync yes master在内存中直接建立rdb,而后发送给slave,不会在本身本地落地磁盘了。
哨兵机制
哨兵的做用就是监控和选举,监控master 和 slave 是否正常,master宕机以后,从新选举
配置过程:
哨兵模式的配置也很是简单,只须要启动一个哨兵的sentinel服务便可。配置信息中有一个须要注意的: sentinel monitor mymaster 192.168.2.7 6379 1 其中192.168.2.7是master的ip 6379是端口,1表明是几个哨兵经过。通常看哨兵服务有多少个。配置通常是n/2 +1 (半数以上)
接下看看master宕机以后:首先会从slave中选取一个做为master。选举完成后会发生以下变化,redis.conf中的,slaveof ip port会变化,sentinel.conf 文件也会发生变化。master的ip 和端口会发生变化。
总而言之,redis的主从复制和哨兵模式服务能够保证redis服务的高可用。
redis的分片存储,单台redis的内存是有限的,若是对于特别大的数据量,就必须使用redis的分片存储了。目前本人并何尝试这种开发,在redis3.0版本以后。redis支持集群的功能,能够解决路由规则(hash算法的均匀分布) 和 动态扩容。能简单的水平扩容,增长节点机器,分片存储。客户端操做面向的是集群。
客户端选择:jedis ,Redisson(相似zk的curator,更上层的封装) Jedis客户端链接有三种方式: 单个redis链接池,哨兵模式下链接池,集群链接池。在不一样的框架中如jedis对于三种链接定义不一样的封装类。 对于后续的redis的分布式锁以及布隆过滤器解决缓存击穿等问题,请持续关注博客更新。
91Code-就要编码,关注公众号获取更多内容!