NoSQL数据库回顾:服务于特定背景的专用数据库,向外提供特定的API,而不是提供通用的SQL接口,因此效率更加高效。html
Redis适用于数据全In memory的场景,支持schema free,auto sharing机制,重要的是其提供了一种disk-backed功能,更像一个增强版的memcached。mysql
Redis最为经常使用的数据类型主要有如下五种:sql
String数据库
Hash数据结构
List运维
Setmemcached
Redis因为支持很是丰富的内存数据结构类型,如何把这些复杂的内存组织方式持久化到磁盘上是一个难题,因此Redis的持久化方式与传统数据库的方式有比较多的差异,Redis一共支持四种持久化方式,分别是:大数据
在设计思路上,前两种是基于所有数据都在内存中,即小数据量下提供磁盘落地功能,然后两种方式则是做者在尝试存储数据超过物理内存时,即大数据量的数据存 储,截止到本文,后两种持久化方式仍然是在实验阶段,而且vm方式基本已经被做者放弃,因此实际能在生产环境用的只有前两种,换句话说Redis目前还只 能做为小数据量存储(所有数据可以加载在内存中),海量数据存储方面并非Redis所擅长的领域。下面分别介绍下这几种持久化方式:url
定时快照方式(snapshot):
该持久化方式实际是在Redis内部一个定时器事件,每隔固定时间去检查当前数据发生的改变次数与时间是否知足配置的持久化触发的条件,若是知足则经过操 做系统fork调用来建立出一个子进程,这个子进程默认会与父进程共享相同的地址空间,这时就能够经过子进程来遍历整个内存来进行存储操做,而主进程则仍 然能够提供服务,当有写入时由操做系统按照内存页(page)为单位来进行copy-on-write保证父子进程之间不会互相影响。
该持久化的主要缺点是定时快照只是表明一段时间内的内存映像,因此系统重启会丢失上次快照与重启之间全部的数据。
基于语句追加方式(aof):
aof方式实际相似mysql的基于语句的binlog方式,即每条会使Redis内存数据发生改变的命令都会追加到一个log文件中,也就是说这个log文件就是Redis的持久化数据。
aof的方式的主要缺点是追加log文件可能致使体积过大,当系统重启恢复数据时若是是aof的方式则加载数据会很是慢,几十G的数据可能须要几小时才能 加载完,固然这个耗时并非由于磁盘文件读取速度慢,而是因为读取的全部命令都要在内存中执行一遍。另外因为每条命令都要写log,因此使用aof的方 式,Redis的读写性能也会有所降低。
虚拟内存方式:
虚拟内存方式是Redis来进行用户空间的数据换入换出的一个策略,此种方式在实现的效果上比较差,主要问题是代码复杂,重启慢,复制慢等等,目前已经被做者放弃。
diskstore方式:
diskstore方式是做者放弃了虚拟内存方式后选择的一种新的实现方式,也就是传统的B-tree的方式,目前仍在实验阶段,后续是否可用咱们能够拭目以待。
有Redis线上运维经验的人会发现Redis在物理内存使用比较多,但尚未超过实际物理内存总容量时就会发生不稳定甚至崩溃的问题,有人认为是基于快 照方式持久化的fork系统调用形成内存占用加倍而致使的,这种观点是不许确的,由于fork 调用的copy-on-write机制是基于操做系统页这个单位的,也就是只有有写入的脏页会被复制,可是通常你的系统不会在短期内全部的页都发生了写 入而致使复制,那么是什么缘由致使Redis崩溃的呢?
答案是Redis的持久化使用了Buffer IO形成的,所谓Buffer IO是指Redis对持久化文件的写入和读取操做都会使用物理内存的Page Cache,而大多数数据库系统会使用Direct IO来绕过这层Page Cache并自行维护一个数据的Cache,而当Redis的持久化文件过大(尤为是快照文件),并对其进行读写时,磁盘文件中的数据都会被加载到物理内 存中做为操做系统对该文件的一层Cache,而这层Cache的数据与Redis内存中管理的数据实际是重复存储的,虽然内核在物理内存紧张时会作 Page Cache的剔除工做,但内核极可能认为某块Page Cache更重要,而让你的进程开始Swap ,这时你的系统就会开始出现不稳定或者崩溃了。咱们的经验是当你的Redis物理内存使用超过内存总容量的3/5时就会开始比较危险了
定时快照方式(snapshot)
基于语句追加文件的方式(aof)
虚拟内存(vm)
Diskstore方式