Redis(六)Redis 和lua 整合及 Redis 持久化

894 阅读8分钟

Redis 和lua 整合

Redis整合lua是对Redis事务的补充

lua

ua是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程 序中,从而为应用程序提供灵活的扩展和定制功能

Redis中使用lua的好处

  • 减少网络开销,在Lua脚本中可以把多个命令放在同一个脚本中运行

  • 原子操作,redis会将整个脚本作为一个整体执行,中间不会被其他命令插入。换句话说,编写脚本的过程中无需担心会出现竞态条件, 隔离性

  • 复用性,客户端发送的脚本会永远存储在redis中,这意味着其他客户端可以复用这一脚本来完成同样的逻辑

Redis整合lua脚本

Redis2.6.0版本开始,通过内置的lua编译/解释器,可以使用EVAL命令对lua脚本进行求值

EVAL命令

  • 在redis客户端中,执行以下命令

    EVAL script numkeys key [key ...] arg [arg ...]

    • 命令说明

      • script参数:是一段Lua脚本程序,它会被运行在Redis服务器上下文中,这段脚本不必(也不应该)定义为一个Lua函数

      • numkeys参数:用于指定键名参数的个数

      • key [key ...]参数: 从EVAL的第三个参数开始算起,使用了numkeys个键(key),表示在脚本中所用到的那些Redis键(key),这些键名参数可以在Lua中通过全局变量KEYS数组,用1为基址的形式访问( KEYS[1] , KEYS[2] ,以此类推)

      • arg [arg ...]参数:可以在Lua中通过全局变量ARGV数组访问,访问的形式和KEYS变量类似(ARGV[1] 、 ARGV[2] ,诸如此类)

    • 示例

      eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second

lua 脚本调用Redis 命令

  • redis.call()

    返回值就是redis命令执行的返回值

    如果出错,返回错误信息,不继续执行

  • redis.pcall()

    返回值就是redis命令执行的返回值

    如果出错了 记录错误信息,继续执行

在脚本中,使用return语句将返回值返回给客户端,如果没有return,则返回nil

  • redis-cli --eval

    可以使用redis-cli --eval命令指定一个lua脚本文件去执行

Redis 持久化

Redis 是一个内存数据库,为了保证数据的持久性,它提供了三种持久化方案

  • RDB 方式(默认)

  • AOF 方式

  • 混合持久化模式(4.0增加,5.0默认开启-当开启AOF时候,它也开启了)它是AOF的一个补充

RDB

RDB 是 Redis 默认采用的持久化方式

RDB 方式是通过快照( snapshotting )完成的,当符合一定条件时 Redis 会自动将内存中的数据进行 快照并持久化到硬盘

触发RDB快照的时机

  • 符合指定配置的快照规则

  • 执行save或bgsave命令 save主线程去快照 bgsave 调用异步线程去快照主线程是单线程 4.0 I/O操作 已经有多线程概念

  • 执行flushall 或flushdb

  • 执行主从复制操作

设置快照规则

  • save 多少秒内 数据变了多少

  • save "" : 不使用RDB存储

  • save 900 1 : 表示15分钟(900秒钟)内至少1个键被更改则进行快照

  • save 300 10 : 表示5分钟(300秒)内至少10个键被更改则进行快照

  • save 60 10000 :表示1分钟内至少10000个键被更改则进行快照

RDB快照的实现原理

快照过程

  • Redis 调用系统中的 fork 函数复制一份当前进程的副本(子进程)

  • 父进程继续接收并处理客户端发来的命令,而子进程开始将内存中的数据写入硬盘中的临时文件

  • 当子进程写入完所有数据后会用该临时文件替换旧的 RDB 文件,至此,一次快照操作完成

fork 是操作系统的函数 linux/ uinx *nux

fork-调用一个子进程,制作快照,生成RDB文件, 替换掉原来的RDB文件

注意事项

  • Redis 在进行快照的过程中不会修改 RDB 文件,只有快照结束后才会将旧的文件替换成新的,也就是说任何时候 RDB 文件都是完整的

  • 这就使得我们可以通过定时备份 RDB 文件来实现 Redis 数据库的备份, RDB 文件是 经过压缩的二进制文件 ,占用的空间会小于内存中的数据,更加利于传输

RDB优缺点

  • 缺点:使用 RDB 方式实现持久化,一旦 Redis 异常退出,就会丢失最后一次快照以后更改的所有数据。这个时候我们就需要根据具体的应用场景,通过组合设置自动快照条件的方式来将可能发生的数据损失控制在能够接受范围。如果数据相对来说比较重要,希望将损失降到最小,则可以使用AOF 方式进行持久化

  • 优点: RDB 可以最大化 Redis 的性能:父进程在保存 RDB 文件时唯一要做的就是 fork 出一个子进程,然后这个子进程就会处理接下来的所有保存工作,父进程无需执行任何磁盘 I/O 操作。同时这个也是一个缺点,如果数据集比较大的时候, fork 可以能比较耗时,造成服务器在一段时间内停止处理客户端的请求

AOF

AOF介绍

默认情况下 Redis 没有开启 AOF ( append only file )方式的持久化

开启 AOF 持久化后,每执行一条会更改 Redis 中的数据的命令, Redis 就会将该命令写入硬盘中的AOF文件,这一过程显然会降低 Redis 的性能,但大部分情况下这个影响是能够接受的,另外使用较快的硬盘可以提高 AOF 的性能

redis.conf

# 可以通过修改redis.conf配置文件中的appendonly参数开启 
appendonly yes 

# AOF文件的保存位置和RDB文件的位置相同,都是通过dir参数设置的。 
dir ./ 

# 默认的文件名是appendonly.aof,可以通过appendfilename参数修改 
appendfilename appendonly.aof

同步磁盘数据

Redis 每次更改数据的时候, aof 机制都会将命令记录到 aof 文件,但是实际上由于操作系统的缓存机制,数据并没有实时写入到硬盘,而是进入硬盘缓存。再通过硬盘缓存机制去刷新到保存到文件

参数说明

# 每次执行写入都会进行同步, 这个是最安全但是是效率比较低的方式 
appendfsync always 
# 每一秒执行(默认) 
appendfsync everysec 
# 不主动进行同步操作,由操作系统去执行,这个是最快但是最不安全的方式 
appendfsync no

最开始的数据它是通过读取内存中的数据,转换成命令。后边的就是每次的更新指令,进行存储

AOF重写原理(优化AOF文件)

Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写。重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合

AOF 文件有序地保存了对数据库执行的所有写入操作, 这些写入操作以 Redis 协议(RESP)的格式保存, 因此 AOF 文件的内容非常容易被人读懂, 对文件进行分析( parse )也很轻松

AOF进行优化时候,并不是读取原来的AOF文件 ,而是读取redis db 进行转化

如何选择RDB和AOF

内存数据库 rdb(redis database)+aof 数据不能丢

缓存服务器 rdb 不建议 只使用 aof (性能差)

恢复时: 先aof再rdb

混合持久化方式

Redis 4.0 之后新增的方式,混合持久化是结合了 RDB 和 AOF 的优点,在写入的时候,先把当前的数据以 RDB 的形式写入文件的开头,再将后续的操作命令以 AOF 的格式存入文件,这样既能保证 Redis 重启时的速度,又能减低数据丢失的风险

RDB 和 AOF 持久化各有利弊,RDB 可能会导致一定时间内的数据丢失,而 AOF 由于文件较大则会影响Redis 的启动速度,为了能同时拥有 RDB 和 AOF 的优点,Redis 4.0 之后新增了混合持久化的方式因此我们在必须要进行持久化操作时,应该选择混合持久化的方式

查询是否开启混合持久化可以使用 config get aof-use-rdb-preamble 命令,执行结果

其中 yes 表示已经开启混合持久化,no 表示关闭,Redis 5.0 默认值为 yes。如果是其他版本的Redis首先需要检查一下,是否已经开启了混合持久化,如果关闭的情况下,可以通过以下两种方式开启

  • 通过命令行开启

  • 通过修改 Redis 配置文件开启

通过命令行开启

使用命令 config set aof-use-rdb-preamble yes

命令行设置配置的缺点是重启 Redis 服务之后,设置的配置就会失效

通过修改 Redis 配置文件开启

在 Redis 的根路径下找到 redis.conf 文件,把配置文件中的 aof-use-rdb-preamble no 改为 aof-use- rdb-preamble yes

配置完成之后,需要重启 Redis 服务器,配置才能生效,但修改配置文件的方式,在每次重启 Redis 服务之后,配置信息不会丢失

需要注意的是,在非必须进行持久化的业务中,可以关闭持久化,这样可以有效的提升 Redis 的运行速度,不会出现间歇性卡顿的困扰