也就是说redis需要经常将内存中的数据同步到磁盘来保证持久化.
redis支持四种持久化方式,
一是?Snapshotting(快照)也是默认方式;
二是Append-only file(缩写aof)的方式;
三是虚拟内存方式;
四是diskstore方式.
一)Snapshotting快照
快照是默认的持久化方式.这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb.可以通过配置设置自动做快照持久化的方式.我们可以配置redis在n秒内如果超过m个key被修改就自动做快照,下面是默认的快照保存配置:
快照保存过程:
① redis调用fork,现在有了子进程和父进程.client?也可以使用save或者bgsave命令通知redis做一次快照持久化.save操作是在主线程中保存快照的,由于redis是用一个主线程来处理所有?client的请求,这种方式会阻塞所有client请求.所以不推荐使用.
另一点需要注意的是,每次快照持久化都是将内存数据完整写入到磁盘一次,并不是增量的只同步脏数据.如果数据量大的话,而且写操作比较多,必然会引起大量的磁盘io操作,可能会严重影响性能.??另外由于快照方式是在一定间隔时间做一次的,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改.如果应用要求不能丢失任何修改的话,可以采用aof持久化方式.下面介绍:
(二)Append-only file
aof?比快照方式有更好的持久化性,是由于在使用aof持久化方式时,redis会将每一个收到的写命令都通过write函数追加到文件中(默认是appendonly.aof).当redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容.当然由于os会在内核中缓存?write做的修改,所以可能不是立即写到磁盘上.这样aof方式的持久化也还是有可能会丢失部分修改.不过我们可以通过配置文件告诉redis我们想要通过fsync函数强制os写入到磁盘的时机.有三种方式如下(默认是:每秒fsync一次):
appendonly yes???#启用aof持久化方式# appendfsync always?#每次收到写命令就立即强制写入磁盘,最慢的,但是保证完全的持久化,不推荐使用appendfsync everysec??#每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,推荐# appendfsync no? ?#完全依赖os,性能最好,持久化没保证
需要注意到是重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点类似.
(三)虚拟内存方式(desprecated)
①.)slow restart重启太慢
下面还是介绍一下redis的虚拟内存.
redis的虚拟内存与os的虚拟内存不是一码事,但是思路和目的都是相同的.就是暂时把不经常访问的数据从内存交换到磁盘中,从而腾出宝贵的内存空间用于其他需要访问的数据.尤其是对于redis这样的内存数据库,内存总是不够用的.除了可以将数据分割到多个redis server外.另外的能够提高数据库容量的办法就是使用vm把那些不经常访问的数据交换的磁盘上.如果我们的存储的数据总是有少部分数据被经常访问,大部分数据很少被访问,对于网站来说确实总是只有少量用户经常活跃.当少量数据被经常访问时,使用vm不但能提高单台redis server数据库的容量,而且也不会对性能造成太多影响.
下面是vm相关配置:
redis的vm在设计上为了保证key的查找速度,只会将value交换到swap文件中.所以如果是内存问题是由于太多value很小的key造成的,那么vm并不能解决.和os一样redis也是按页面来交换对象的.redis规定同一个页面只能保存一个对象.但是一个对象可以保存在多个页面中.
参数配置讨论完后,在来简单介绍下vm是如何工作的:当vm-max-threads设为0时(Blocking VM)
当vm-max-threads大于0(Threaded VM)换出:??当主线程检测到使用内存超过最大上限,会将选中的要交换的对象信息放到一个队列中交由工作线程后台处理,主线程会继续处理client请求.换入:??如果有client请求的key被换出了,主线程先阻塞发出命令的client,然后将加载对象的信息放到一个队列中,让工作线程去加载.加载完毕后工作线程通知主线程.主线程再执行client的命令.这种方式只阻塞请求value被换出key的client
看完小编介绍的blocking vm的方式总的性能会好一些,因为不需要线程同步,创建线程和恢复被阻塞的client等开销.但是也相应的牺牲了响应性.threaded vm的方式主线程不会阻塞在磁盘io上,所以响应性更好.如果我们的应用不太经常发生换入换出,而且也不太在意有点延迟的话则推荐使用blocking vm的方式.
关于redis vm的更详细介绍可以参考下面链接:??http://antirez.com/post/redis-virtual-memory-story.html??http://redis.io/topics/internals-vm
(四)diskstore方式
①.)?读操作,使用read through以及LRU方式.内存中不存在的数据从磁盘拉取并放入内存,内存中放不下的数据采用LRU淘汰.
由于写操作是单线程,即使cache-flush-delay设成0,多个client同时写则需要排队等待,如果队列容量超过cache-max-memory Redis设计会进入等待状态,造成调用方卡住.
-??通过BGSAVE可以随时将diskstore格式另存为rdb格式,而且rdb格式还用于Redis复制以及不同存储方式之间的中间格式.
-??通过工具可以将rdb格式转换成diskstore格式.
下面介绍一下Diskstore的算法.
dsKeyToPath(key):
char *hashKey = sha1(key);
path[0] = hashKey[0];
path[1] = hashKey[1];
return path;
存储算法(如key == apple):
dsSet(key, value, expireTime):
char *path = dsKeyToPath(hashKey);
rdbSaveKeyValuePair(fp, key, value, expireTime);
fclose(fp)
获取算法:
dsGet(key):
robj *val = rdbLoadObject(fp);
return val;
以上就是土嘎嘎小编为大家整理的Redis 持久化,写入磁盘的方式相关主题介绍,如果您觉得小编更新的文章只要能对粉丝们有用,就是我们最大的鼓励和动力,不要忘记讲本站分享给您身边的朋友哦!!