第四章 数据安全与性能保障
- 将数据持久化至硬盘
- 将数据复制至其他机器
- 处理系统故障
- Redis 事务
- 非事务型流水线 (non-transactional pipeline)
- 诊断性能问题
本章将会说明同时使用复制和持久化的好处和坏处。
4.1.持久化选项
快照 (snapshotting)
——将存在于某一时刻的所有数据都写入硬盘里面。只追加文件 (append-only file , AOF)
——在执行写命令是,将被执行的写命令复制到硬盘里面。
4.1.1.快照持久化
创建快照的办法有以下几种:
- 客户端可以通过向 Redis 发送
bgsave
命令来创建一个快照。 - 客户端还可以通过向 Redis 发送
save
命令来创建一个快照,接到save
命令的 Redis 服务器在快照创建完毕之前将不再响应任何其他命令。 - 如果用户设置了
save
配置选项。Redis 就会自动触发bgsave
命令。如果用户设置了多个save
配置选项,那么当任意一个条件被满足,Redis 就会触发一次bgsave
命令。 - 当 Redis 通过
shutdown
命令接收到关闭服务器的请求时,或者接收到标准TERM
信号时,会执行一个save
命令,阻塞所有客户端,不再执行客户端发送的任何命令,并在save
命令执行完毕之后关闭服务器。 - 当一个 Redis 服务器连接另一个 Redis 服务器,并向对方发送
sync
命令来开始一次复制操作的时候,如果主服务器目前没有在执行bgsave
操作,或者主服务器并非刚刚执行完bgsave
操作,那么主服务器就会执行bgsave
命令。
- 个人开发
考虑的是尽可能地降低快照持久化带来的资源消耗。 - 对日志进行聚合计算
考虑:如果 Redis 因为崩溃而未能成功创建新的快照,那么我们能够承受丢失多长时间以内产生的新数据。 - 大数据
如果 Redis 的内存占用量达到数十个 GB ,并且剩余的空闲内存并不多,或者 Redis 运行在虚拟机 (virtual machine) 上面,那么执行bgsave
可能会导致系统长时间地停顿,也可能引发系统大量地使用虚拟内存 (virtual memory) ,从而导致 Redis 的性能降低至无法使用的程度。
为了防止 Redis 因为创建子进程而出现停顿,可以考虑关闭自动保存,转而通过手动发送bgsave
和save
来进行持久化。手动发送bgsave
一样会引发停顿,但可以自行控制时间。另外,save
会一直阻塞 Redis 直到快照生成完毕,但是因为它不需要创建子进程,所以不会像bgsave
一样因为创建子进程而导致 Redis 停顿;并且因为没有子进程争抢资源,所以save
创建快照的速度会比bgsave
更快一些。
4.1.2. AOF 持久化
文件同步
选项 | 同步频率 |
---|---|
always | |
everysec | |
no |
警告:固态硬盘和 appendfsync always
4.1.3.重写/压缩 AOF 文件
4.2.复制
复制 (replication)
sunionstore 命令的性能
4.2.1.对 Redis 的复制相关选项进行配置
尽管有多个不同
4.2.2. Redis 复制的启动过程
步骤 | 主服务器操作 | 从服务器操作 |
---|---|---|
1 | ||
2 | ||
3 | ||
4 | ||
5 |
实际中
从服务器在进行同步时,会清空自己的所有数据
警告:Redis 不支持主主复制 (master-master replication)
4.2.3.主从链
4.2.4.检验硬盘写入
INFO 命令中的其他信息
4.3.处理系统故障
提供了 ACID1
4.3.1.验证快照文件和 AOF 文件
校验和 (checksum) 与散列值 (hash)
4.3.2.更换故障主服务器
Redis Sentinel
4.4.Redis 事务
延迟执行事务有助于提升性能
4.4.1.定义用户信息和用户包裹
4.4.2.将商品放到市场上销售
/*list_item() 函数*/
def list_item(conn,itemid,sellerif,price):
4.4.3.购买商品
/*purchase_item() 函数*/
def purchase_item(conn,buyerid,itemid,sellerid,lprice):
为什么 Redis 没有实现典型的加锁功能?
4.5.非事务型流水线
/*之前在 2.5 节中展示过的 update_token() 函数*/
/*update_token_pipeline() 函数*/
def update_token_pipeline(conn,token,user,item=None):
/*benchmark_update_token() 函数*/
def benchmark_update_token(conn,duration)
描述 | 宽带 | 延迟值 | 每秒调用 update_table() 的次数 | 每秒调用 update_table_pipeline 的次数 |
---|
4.6.关于性能方面的注意事项
性能或者错误 | 可能的原因 | 解决方法 |
---|
ACID 是指原子性 (atomicity)、一致性 (consistency)、隔离性 (isolation) 和耐久性 (durability),如果一个数据库想要实现可靠的数据事务,那么它就必须保证 ACID 性质。 ↩︎