redis学习(三)
如何保障reids的数据安全和性能?
一.持久化选项
1.快照snapshotting
它可以将存在于某一时刻的所有数据都写入硬盘里面。
配置选项示例: save 60 1000 注:从最近一次创建快照之后开始算起,60秒之内有1000次写入满足条件之后,redis开始快照保存。
2.追加文件(append-only-file) AOF
在执行命令时,将被执行的命令复制到硬盘里面。
配置选项示例:appendonly no
两种配置都要配置文件输出位置:
示例:dir /data/redis
注:将内存中的数据存储到硬盘的一个主要原因就是为了重用数据,或者是为了防止系统故障而将数据备份到一个远程位置。
二。快照持久化详细
1 .快照的作用
redis可以通过创建快照来获得存储在内存里面的数据在某个时间点上的副本。可以将快照复制到其他服务器从而创建具有相同数据的服务器副本,还可以将快照留在本地以便重启服务器时使用。
2.快照的缺点:
示例: 设置了60s 内 满足1000条写入命令 如果服务器在刚刚满足这个条件创建了快照,之后又小于1000条写入命令 并且还没有到60s, 这个时候服务器崩溃了,那么redis重启之后,这些数据将会丢失。
因为快照了数据本身,如果数据量大的话,占用磁盘也是一笔不小的开销。
3.快照的优点:
重启恢复快,存储在本地,下次启动数据恢复快。
4.创建快照的办法
(1).客户端发送bgsave 命令来创建一个快照,redis会调用fork来创建一个子线程,然后负责将快照写入硬盘,而父进程继续处理命令请求。
(2).客户端发送save命令来创建一个快照,接受save命令的redis服务器在快照创建完毕之前不在响应任何命令。一般不常用save命令,只有在没有足够内存下,或者等待持久化完毕也无所谓的情况下,才会使用这个命令。
(3)如果用户设置了save选项,比如 save 60 1000 那么从redis最近一次创建快照之后开始算起,满足60s有1000个写入命令就会调用bgsave命令。如果配置多个save选项,当有条件满足就会触发bgsave命令。
(4) 当一个redis服务器连接另一个redis服务器,并向对方发送sync命令来开始一次复制操作的时候,如果主服务器没有执行bgsave操作,或者主服务器并非刚刚执行完bgsave操作,那么主服务器就会执行bgsave命令。
注: 只使用快照来保存数据时,如果系统发送崩溃,用户将丢失最近一次生成之后更改的所有数据。
三。AOF持久化详细
如果用户不能容忍数据的丢失,那么可以使用aof持久化来存储在内存里的数据尽快地保存到硬盘里。
简单的来说,aof持久化会将被执行的写命令写到aof文件的末尾,以此来记录数据发生的变化。
文件同步,写入文件时会发生3件事,file.write()写入的文件会放在缓冲区,而数据只有写到硬盘才算成功,用户可以调用file.flush()这个操作是告诉操作系统尽快清空缓冲区,最后用户还可以命令操作系统将文件同步sync到硬盘,同步操作会一直阻塞知道指定文件被写入硬盘为止。
1.aof的appendonly3个同步频率
always 每个写入命令都要同步写入到硬盘,这样做会严重降低redis的速度
everysec 每秒执行一次同步,显示地将多个写命令到硬盘
no 让操作系统来决定何时进行同步。
注: 如果使用了appendonly always 使用固态硬盘不断写入少量数据的做法可能会引发严重的写入放大问题,在某些情况下会使固态硬盘的使用寿命降低。
为了兼顾数据安全和写入性能,用户可以考虑使用appendfsync everysec 让redis每一秒的频率对aop文件进行同步,用户也最多丢失一秒的数据。
aof持久化优点:
保证数据的安全性,并且减少性能消耗
aof持久化的缺点:
(1)用户不断的往aof文件里写入日志,体积不断增大的aof文件甚至可能用完硬盘空间。
(2)如果aof文件的体积非常大,redis重启通过aof文件记录的所有写命令来还原数据集,那么还原操作执行的时间就会可能非常长。
解决aof体积不断增大的问题,可以向redis发送bgrewriteaof命令,这个命令会通过移除aof文件中冗余命令来重写aof,使aof文件的体积尽可能变小。这个命令和bgsave的工作原理很相似,redis会创建一个子进程负责对aof文件进行重写。如果对体积比较大额aof重写的话会造成操作系统挂起几秒,可以按照设置快照一样设置自动重写aof的配置
可以通过设置auto-aof-rewrite-percentage 和 auto-aof-rewrire-min-size 选项来自动执行bgrewriteaof
示例: auto-aof-rewrite-percentage 100
auto-aof-rewrire-min-size 64mb
aof文件达到64Mb 并且比上次重写的aof文件大一倍
无论使用快照还是aof这种方式,必须对持久化所得的文件进行备份,最好是备份到不多的服务器中去,这样才能避免数据丢失事故发生。
四。复制
通过aof持久化或者快照持久化,可以在系统重启或者崩溃的情况下仍然保留数据,随着负载量的上升,或者数据的完整性变得越来越重要时,用户可能需要使用复制特性。复制可以让其他服务器拥有一个不断更新的数据副本,从而使得拥有数据副本的服务器可以使用用户处理客户端发送的请求。关系数据库通常会使用一个主服务器向多个从服务器发送更新,redis也采用同样的方法实现自己的复制特性,并将作为一种扩展性能的一种手段。
1.复制配置
在创建快照方式中有redis服务器向redis服务器发送sync命令也会出发bgsave命令,使用前提必须服务器已经设置 dir 和dbfilename选项,并且这两个目录都是可写的。
开启从服务器所必须的选项只有slaveof一个,在启动redis服务器的时候,指定一个包含slaveof host port 选项的配置文件,那么redis服务器将根据选项给定的ip地址和端口来连接主服务器,对应一个正在运行的redis服务器,可以发送slaveof no one 命令来让服务器终止复制曹操,不再接受主服务器的数据更新,也可以用个发送slaveod host port 命令来让服务器开始复制一个新的主服务器。
2.复制过程
1.等待命令进入
2.开始执行bgsave,并使用缓冲区记录bgsave之后执行的所有写命令
3.bgsave执行完毕,向从服务器发送快照文件,并在发送期间继续使用缓冲区记录被执行的写命令。
4。快照文件发送完毕,开始向从服务器发送存储在缓冲区里面的写命令。
5.缓冲区存储的写命令发送完毕,从现在开始,每执行一个写命令,就向从服务器发送相同的写命令。
一般主服务器最好留足够的内存和带宽来执行复制到从服务器中去,最好主服务器只使用50%-65% 剩下的留给从服务器使用。从服务型进行同步,会清空自己的所有数据,从服务器在于服务器进行初始连接时,数据库中原有数据将会丢失,并替换成主服务器发来的数据。
注: redis不支持主主复制。
3.检查硬盘写入
对于每秒同步aof文件redis来说,可以通过发送info命令 在输出结果中 aof_pending_bio_fsync 属性的值是否为0
至此: redis持久化的解决方案 使用aof和复制来保证数据安全和性能。
五. 处理系统故障
redis跟提供ACID保证的传统关系数据不同,用户需要多做一些工作才能保障数据的一致性
1.验证快照文件和aof文件命令
redis-check-aof / redis-check-dump在系统崩溃之后,检查aof文件和快照文件的状态,并在需要的时候对文件进行修复。
如果使用aof文件, 那么使用redis-chekc-aof --fix <file.aof> 扫描给定的aof文件,目前没有修复快照文件的办法,快照最好就是备份。
2.更换故障主服务器
假设A,B两台运行着redis,其中A为主服务器,如果A主服务器崩溃了,如果让C服务器成为主服务器
第一步向B发送save命令,让B创建一个快照文件,接着将这个快照文件发给机器C,并在机器C上启动redis,最后让B成为C的从服务器。
redis还有一个哨兵模式 自动监控主服务器挂掉之后会自动进行故障转移。
3.redis事务
前面通过了multi将要执行的多个命令一起发送给redis,除了这个之外只是保障redis按顺序执行,还是不能防止其他redis客户端对这些命令的键进行替换,更新,删除操作,这是时候需要加上watch操作,如果发现对这些命令的键进行替换,更新和删除,在用户尝试exec命令的时候,事务将失败并返回一个错误,UNwatch命令可以在watch执行之后,multi命令执行之前对连接进行重置,同样地,discard也可以在multi执行之后,exec执行值前对连接rest,也就是说,用户在使用watch监视一个或多个键,接着开始使用multi开始一个新的事务,并将多个命令入队列事务之后,仍然可以通过发送discard来取消watch命令并清空所有已经入队列的命令。
4.为什么redis没有实现典型的加锁功能,关系型数据库会对被访问的数据进行加锁,直到事务被提交或者被回滚为止。如果有客户端试图对被加锁的数据进行写入,那么客户端一直被阻塞。缺点在于效率低。属于悲观锁
redis尽可能减少客户端等待的时间,并不会在执行watch命令的时候加锁,而是在其他客户端修改了键的值,通知执行watch的客户端,这种做法属于乐观锁,只需要客户端失败重试就行。
redis提供了pipeline流水线执行redis的命令,减少通信次数,如果设置pipeline传入的参数为true,则会用multi和exec将命令包裹一起发给redis.如果为false 。redis只是将命令一条条的放在pipeline里。这样会减少通信次数。
六。性能方面
如果要知道一个redis的命令到底跑多快。可以执行redis-benchmark 来了解redis在自己服务器上的各种性能特征。如果不给定参数的话,默认是50个客户端进行性能测试
语法: redsi-benchmark -c 1 -q 注: -c是使用多少个客户端 -q是让程序简化输出结果
考察redis-benchmark 输出结果是不要把结果看着事redis的实际性能。因为这个命令不会出来命令返回回复,所以实际性能可能只有50%到60%。
每次学习都是在走人生路