文档章节

Redis实战 - 数据安全与性能保障

kukudeku
 kukudeku
发布于 2017/04/13 16:02
字数 3725
阅读 61
收藏 0

一、持久化选项介绍

Redis提供了两种不同的持久化方法来将数据存储到硬盘。一种方法叫快照(snapshotting),它可以将存在于某一时刻的所有数据都写入到硬盘里面。另一种方法叫只追加文件(append-only file, AOF),它会在执行写命令时,将被执行的写命令复制到硬盘。

1.1 快照持久化选项:

save 60 1 # 60秒内有1次写入操作的时候执行快照的创建

stop-writes-on-gbsave-error no #创建快照失败的时候是否仍然继续执行

rdbcompression yes #是否对快照文件进行压缩

dbfilename dump.rdb #如何命名硬盘上的快照文件

dir ./ #快照文件保存的位置

在redis配置文件redis.conf中内容如下:

1.2 AOF 持久化选项

appendonly on #是否使用AOF持久化

appendsync everysec #多久执行一次将写入内容同步到硬盘

no-appendfsync-on-rewrite no #对AOF进行压缩的同时能否执行同步操作

auto-aof-rewrite-percentage 100 #多久执行一次AOF压缩

auto-aof-rewrite-min-size 64mb #多久执行一次AOF压缩

dir ./ #AOF所保存的位置

这两种持久化方法既可以同时使用,用可以单独使用,具体选择那种持久化方法需要根据用户的数据以及应用决定。

二、快照持久化

Redis可以通过创建快照来获得存储在内存里面的数据在某个时间点上的副本。在创建快照之后,用户可以对快照进行备份,可以将快照复制到其他服务器从而创建具有相同数据的服务器副本,还可以将快照留在原地以便重启服务器时使用。

如果在新的快照文件创建完毕之前,Redis、系统或者硬件这三者中任意一个崩溃了,那么Redis将丢失最近一次创建快照之后写入的所有数据。

创建快照的办法有以下几种:

  • 客户端可以向Redis发送BGSAVE 命令来创建快照。对于支持BGSAVE命令的平台来说,Redis会调用fork来创建一个子进程,然后子进程负责将快照写入到硬盘,而父进程则继续处理命令请求。
  • 客户端还可以向Redis发送SAVE命令来创建快照。接到SAVE命令的Redis服务器在快照创建完毕之前将不再响应任何其他命令。SAVE不常用,我们通常只会在没有足够内存去执行BGSAVE命令的时候才会使用这个命令。
  • 如果用户设置了save配置选项,那么当任意一个save配置选项所设置的条件被满足时,Redis就会触发一次BGSAVE命令。
  • 当Redis通过SHUTDOWN命令接收并关闭服务器请求时,或者接收到标准TERM信号时,会执行一次SAVE,阻塞客户端,不再执行客户端发送的任何命令,并在SAVE命令执行完毕之后关闭服务器
  • 当一个Redis服务器连接到另一个Redis服务器,并向对方发送SYNC命令来开始复制操作的时候,如果主服务器目前没有在执行BGSAVE操作,或者主服务器并非刚刚执行完BGSAVE操作,那么主服务器就会执行BGSAVE。

当Redis存储的数据量只有几个GB的时候,使用快照来保存数据时没有问题的。Redis会创建子进程并将数据保存到硬盘里,生成快照的时间很短。但是随着Redis占用内存越来也多,BGSAVE在创建子进程时耗费时间会越来越多。如果Redis的内存占用量达到数十个GB,并且剩余的空间内存并不多时,执行BGSAVE可能导致系统长时间停顿,从而导致Redis的性能降低甚至无法使用。在这种情况下,我们可以使用AOF持久化来将存储在内存里面的数据尽快地保存到硬盘里面

三、AOF持久化

简单来说AOF持久化会将被执行的命令写到AOF文件的末尾,以此来记录数据发生的变化。因此,Redis只要从头到尾地重新执行一次AOF文件包含的所有写命令,就可以恢复AOF文件所记录的数据集。

我们可以通过变更redis.conf下的appendonly属性yes来打开AOF。更改appendfsync属性为everysec/always/no来配置AOF文件的同步频率

appendfsync同步频率的区别如下:

选项 同步频率
always 每个Redis写命令都要同步写入硬盘,这样会严重降低Redis的速度
everysec 每秒执行一次同步,显示地将多个写命令同步到硬盘
no 让操作系统决定应该何时进行同步
  1. always的方式固然可以对没一条数据进行很好的保存,但是这种同步策略需要对硬盘进行大量的写操作,所以Redis处理命令的速度会受到硬盘性能的限制。普通的硬盘每秒钟只能处理大约200个写命令,使用固态硬盘SSD每秒可以处理几万个写命令,但是每次只写一个命令,这种只能怪不断地写入很少量的数据的做法有可能引发严重的写入放大问题,这种情况下降严重影响固态硬盘的使用寿命。
  2. everysec的方式,Redis以每秒一次的频率大队AOF文件进行同步。这样的话既可以兼顾数据安全也可以兼顾写入性能。Redis以每秒同步一次AOF文件的性能和不使用任何持久化特性时的性能相差无几,使用每秒更新一次 的方式,可以保证,即使出现故障,丢失的数据也在一秒之内产生的数据。
  3. no的方式,Redis将不对AOF文件执行任何显示的同步操作,而是由操作系统来决定应该何时对AOF文件进行同步。这个命令一般不会对Redis的性能造成多大的影响,但是当系统出现故障的时候使用这种选项的Redis服务器丢失不定数量的数据。另外,当用户的硬盘处理写入操作的速度不够快的话,那么缓冲区被等待写入硬盘的数据填满时,Redis的写入操作将被阻塞,并导致Redis处理命令请求的速度变慢,因为这个原因,一般不推荐使用这个选项。

四、重写/压缩 AOF文件

因为Redis会不断地将被执行的写命令记录到AOF文件里面,所以随着Redis不断运行,AOF文件的体积也会不断增长,在极端情况下,体积不断增大的AOF文件甚至可能会用完硬盘的所有可用空间。另外,因为Redis在重启之后需要通过重新执行AOF文件记录的所有命令来还原数据集,所以当AOF体积非常大的时候,还原操作需要的时间会非常长

为了解决AOF体积不断增大的问题,用户可以向Redis发送BGREWRITEAOF命令,这个命令会通过移除AOF文件中的冗余命令来重写AOF文件,使得AOF文件的体积变得尽可能的小。

BGREWRITEAOF命令会让Redis创建一个子进程对AOF文件进行重写。AOF持久化可以通过设置auto-aof-rewrite-percentage选项和auto-aof-rewrite-min-size选项来自动执行BGREWRIRWAOF。

示例:auto-aof-rewrite-percentage 100和auto-aof-rewrite-min-size 64mb表示当AOF文件的体积大于64mb,并且AOF文件的体积比上一次重写之后的体积大了至少一倍的时候,Redis将执行BGREWRITEAOF命令。

五、复制

复制可以让其他服务器拥有一个不断更新的数据副本,从而使得拥有数据副本的服务器可以用于处理客户端发送的读请求。

5.1 对Redis的复制相关选项进行配置

从服务器连接主服务器时,主服务器会执行BGSAVE操作。为了正确使用复制特性,用户需要保证主服务器已经正确配置了持久化清单(快照和aof持久化)。而且开启从服务器所必须的选项中只有slaveof一个。如果用户在启动Redis服务器时,指定了一个包含slaveof host port选项的配置文件,那么Redis服务器将根据该选项给定的IP地址和端口号来连接主服务器。

5.2 Redis 复制的启动过程

步骤 主服务器操作 从服务器操作
1 (等待命令进入) 连接(或者重连接)主服务器,发送SYNC命令
2 开始执行BGSAVE,并使用缓冲区记录BGSAVE之后执行的所有命令 根据配置选项来决定是继续使用现有数据(如果有数据的话)来处理客户端的命令请求,还是向发送请求的客户端返回错误
3 BGSAVE执行完毕,向从服务器发送快照文件,并在发送期间继续使用缓冲区记录被执行的写命令 丢弃所有的旧数据(如果有的话),开始载入主服务器发来的快照文件
4 快照文件发送完毕,开始向从服务器发送存储在缓冲区的写命令 完成对快照文件的解释操作,像往常一样开始接受客户的命令请求
5 缓冲区存储的写命令发送完毕;从现在开始,每执行一个写命令,就向从服务器发送相同的写命令 执行主服务器发来的所有存储在缓冲区里面的写命令;从现在开始,接收并执行主服务器传来的每个写命令

用户可以通过配置SLAVEOF host port 来将一个Redis服务器设置为从服务器,也可以通过向正在运行中的Redis服务器发送SLAVEOF命令来将其设置为从服务器。如果用户使用的是SLAVEOF配置选项,那么Redis在启动时首先会载入当前可用的任何快照或者AOF文件,然后连接主服务器并执行复制过程。如果用户使用的是SLAVEOF命令,那么Redis会立即尝试连接服务器,如果连接成功,那么开始执行复制过程。

5.3 主从链

因为Redis的主服务器和从服务器没有特别不同的地方,所以从服务器也可以拥有自己的从服务器,并由此形成主从链。

为了将数据保存到多台机器上面,用后首先需要为主服务器设置多个从服务器,然后对每个从服务器设置appendonly yes选项和appendfsync everysec选项,这样的话,用后就可以让多台服务器以每秒一次的频率将数据同步到硬盘了。

5.4 检查硬盘写入

为了验证主服务器是否已经将写数据发送至从服务器,用户需要在向主服务器写入真正的数据之后,再向主服务器写入一个唯一的虚构值,然后通过检查虚构值是否存在于从服务器来判断写数据是否已经到达从服务器。另外,可以通过检查INFO命令的输出结果中aof_pending_bio_fsync实行是否为0,如果是的话,那么就表示服务器已经将已知的所有数据都保存到硬盘里了。咋向主服务器写入数据之后,用户可以将主服务器和从服务器的连接作为参数,来检查硬盘写入。

info命令结果如下(无关信息太多,以省略号代替):

127.0.0.1:6379> info

# Server

redis_version:3.2.8

redis_git_sha1:00000000

redis_git_dirty:0

redis_build_id:3adf919ae7e68908

redis_mode:standalone

os:Linux 2.6.32-642.6.2.el6.i686 i686

...

executable:/usr/local/bin/redis-server

config_file:/usr/local/soft/redis-stable/redis.conf


# Clients

connected_clients:1

...


# Memory

used_memory:646640

...

mem_allocator:jemalloc-4.0.3


# Persistence

loading:0

rdb_changes_since_last_save:0

rdb_bgsave_in_progress:0

rdb_last_save_time:1492011141

rdb_last_bgsave_status:ok

rdb_last_bgsave_time_sec:0

rdb_current_bgsave_time_sec:-1

aof_enabled:0

aof_rewrite_in_progress:0

aof_rewrite_scheduled:0

aof_last_rewrite_time_sec:-1

aof_current_rewrite_time_sec:-1

aof_last_bgrewrite_status:ok

aof_last_write_status:ok


# Stats

total_connections_received:55

total_commands_processed:299

instantaneous_ops_per_sec:0

total_net_input_bytes:9774

total_net_output_bytes:29924707

instantaneous_input_kbps:0.00

instantaneous_output_kbps:0.00

rejected_connections:0

sync_full:0

sync_partial_ok:0

sync_partial_err:0

expired_keys:0

evicted_keys:0

keyspace_hits:181

keyspace_misses:1

pubsub_channels:0

pubsub_patterns:0

latest_fork_usec:178

migrate_cached_sockets:0


# Replication

...

# CPU

...

# Cluster

cluster_enabled:0


# Keyspace

db0:keys=6,expires=0,avg_ttl=0

六、处理系统故障

6.1 验证快照文件和AOF文件

无论是快照持久化还是AOF持久化,都提供了在遇到系统瓶颈故障时进行数据恢复的工具。Redis提供了两个命令行程序redis-check-aof和redis-check-dump/redis-check-rdb,他们可以在系统故障发生之后,检查AOF文件和快照文件的状态,并在有需要的情况下对文件进行修复。

如果在运行运行redis-check-aof程序时给定了--fix参数,那么程序将对AOF文件进行修复。它会扫描AOF文件,寻找不正确或者不完成的命令,当发现第一个出错命令的时候,程序会删除出错的命令以及位于出错命令之后的所有命令。

6.2 更换故障主服务器

假设A、B两台服务器都运行着Redis,其中机器A的Redis为主服务器,而B的Redis为从服务器。不巧的是,机器A刚刚因为某个故障断开了网络连接,因此用户决定将同样安装了Redis的机器C用作新的主服务器。

更换服务器的计划非常简单:首先向机器B发送一个SAVE命令,让它创建一个新的快照文件,接着将这个快照文件发送给机器C,并在机器C上启动Redis。最后让机器B成为机器C的从服务器。

七、Redis事务

Redis事务是以特殊命令MULTI为开始,之后跟着用户传入的多个命令,最后以EXEC为结束。但是由于这种简单的事务在EXEC命令被调用之前不会执行任何实际操作,所以用户将没办法根据读取到的数据来做决定。为此Redis采用了延迟执行事务(一次性发送多个命令,然后等待所有回复出现)以提高性能,减少客户端与Redis服务器之间的网络通信次数来提升Redis在执行多个命令时的性能。

© 著作权归作者所有

下一篇: 认识Redis
kukudeku
粉丝 121
博文 49
码字总数 121805
作品 0
杭州
程序员
私信 提问
飞天技术汇 | 阿里云Redis产品升级大全

阿里云Redis重磅产品升级:全球多活版、混合存储版、多线程性能增强版。 这期飞天技术汇你将看到 ● 企业如何实现业务快速全球化布局 ● 冷热数据如何分离 ● 多IO线程如何面对高并发业务 助...

阿里云头条
2018/09/03
0
0
云数据库 Redis 版功能特性

关于云数据库 Redis 版详细了解: 云数据库 Redis 版使用教程 (云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高...

mcy0425
2018/03/02
22
0
Redis——持久化

RDB(半持久化模式) 1.1 原理 直接把内存数据存储到dump临时文件中,然后替换旧的dump。 1.2 手动执行持久化 1.2.1 save 在Redis主线程工作 尽量避免使用 1.2.2 bgsave 调用Fork产生子进程 ...

Mr-想
2018/01/23
12
0
Asp.Net Core 2.0 项目实战(6)Redis配置、封装帮助类RedisHelper及使用实例

Asp.Net Core 2.0 项目实战(1) NCMVC开源下载了 Asp.Net Core 2.0 项目实战(2)NCMVC一个基于Net Core2.0搭建的角色权限管理开发框架 Asp.Net Core 2.0 项目实战(3)NCMVC角色权限管理前...

郑州-在路上
2018/05/17
0
0
java程序员从入门到精通

前言 java路漫漫,这是一份针对java服务端开发入门与进阶指南。 建议: 尽量用 google 查找技术资料。 有问题在 stackoverflow 找找,大部分都已经有人回答。 多看官方的技术文档。 ibm deve...

rock912
2016/07/04
123
4

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周日乱弹 —— 我,小小编辑,食人族酋长

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @宇辰OSC :分享娃娃的单曲《飘洋过海来看你》: #今日歌曲推荐# 《飘洋过海来看你》- 娃娃 手机党少年们想听歌,请使劲儿戳(这里) @宇辰OSC...

小小编辑
40分钟前
84
5
spring cloud

一、从面试题入手 1.1、什么事微服务 1.2、微服务之间如何独立通讯的 1.3、springCloud和Dubbo有哪些区别 1.通信机制:DUbbo基于RPC远程过程调用;微服务cloud基于http restFUL API 1.4、spr...

榴莲黑芝麻糊
今天
2
0
Executor线程池原理与源码解读

线程池为线程生命周期的开销和资源不足问题提供了解决方 案。通过对多个任务重用线程,线程创建的开销被分摊到了多个任务上。 线程实现方式 Thread、Runnable、Callable //实现Runnable接口的...

小强的进阶之路
昨天
6
0
maven 环境隔离

解决问题 即 在 resource 文件夹下面 ,新增对应的资源配置文件夹,对应 开发,测试,生产的不同的配置内容 <resources> <resource> <directory>src/main/resources.${deplo......

之渊
昨天
8
0
详解箭头函数和普通函数的区别以及箭头函数的注意事项、不适用场景

箭头函数是ES6的API,相信很多人都知道,因为其语法上相对于普通函数更简洁,深受大家的喜爱。就是这种我们日常开发中一直在使用的API,大部分同学却对它的了解程度还是不够深... 普通函数和...

OBKoro1
昨天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部