Redis(三) -- 其他数据类型和数据持久化

其他数据类型

List

LPUSH

LPUSH key value [value ...]
-- 将一个或多个值 value 插入到列表 key 的表头
-- 如果有多个 value 值,那么各个 value 值按从左到右的顺序依次插入到表头: 比如说,对空列表 mylist 执行命令 LPUSH mylist a b c ,列表的值将是 c b a ,这等同于原子性地执行 LPUSH mylist a 、 LPUSH mylist b 和 LPUSH mylist c 三个命令。
-- 如果 key 不存在,一个空列表会被创建并执行 LPUSH 操作。
-- 当 key 存在但不是列表类型时,返回一个错误。

-- 返回值:执行 LPUSH 命令后,列表的长度。

-- 加入单个元素
redis> LPUSH languages python
(integer) 1


--- 加入重复元素

redis> LPUSH languages python
(integer) 2

redis> LRANGE languages 0 -1     -- 列表允许重复元素
1) "python"
2) "python"


-- 加入多个元素

redis> LPUSH mylist a b c
(integer) 3

-- 查看元素
redis> LRANGE mylist 0 -1
1) "c"
2) "b"
3) "a"

RPUSH

RPUSH key value [value ...]
-- 将一个或多个值 value 插入到列表 key 的表尾(最右边)。
-- 如果有多个 value 值,那么各个 value 值按从左到右的顺序依次插入到表尾:比如对一个空列表 mylist 执行 RPUSH mylist a b c ,得出的结果列表为 a b c ,等同于执行命令 RPUSH mylist a 、 RPUSH mylist b 、 RPUSH mylist c 。
-- 如果 key 不存在,一个空列表会被创建并执行 RPUSH 操作。
-- 当 key 存在但不是列表类型时,返回一个错误。

-- 返回值:执行 RPUSH 操作后,表的长度。

-- 添加单个元素
redis> RPUSH languages c
(integer) 1


-- 添加重复元素
redis> RPUSH languages c
(integer) 2

redis> LRANGE languages 0 -1
1) "c"
2) "c"

-- 添加多个元素

redis> RPUSH mylist a b c
(integer) 3

LPOP

LPOP key
-- 移除并返回列表 key 的头元素。

--返回值:列表的头元素。
-- 当 key 不存在时,返回 nil 。

-- 返回列表的长度
redis> LLEN course
(integer) 0

redis> RPUSH course algorithm001
(integer) 1

redis> RPUSH course c++101
(integer) 2

redis> LPOP course  -- 移除头元素
"algorithm001"

RPOP

RPOP key
-- 移除并返回列表 key 的尾元素。

-- 返回值:
-- 列表的尾元素。
-- 当 key 不存在时,返回 nil 。

redis> RPUSH mylist "one"
(integer) 1

redis> RPUSH mylist "two"
(integer) 2

redis> RPUSH mylist "three"
(integer) 3

redis> RPOP mylist           -- 返回被弹出的元素
"three"

redis> LRANGE mylist 0 -1    -- 列表剩下的元素
1) "one"
2) "two"

BLPOP

BLPOP key [key ...] timeout
-- BLPOP 是列表的阻塞式(blocking)弹出原语。
-- 它是 LPOP 命令的阻塞版本,当给定列表内没有任何元素可供弹出的时候,连接将被 BLPOP 命令阻塞,直到等待超时或发现可弹出元素为止。
-- 当给定多个 key 参数时,按参数 key 的先后顺序依次检查各个列表,弹出第一个非空列表的头元素。


-- 非阻塞行为:
-- 当 BLPOP 被调用时,如果给定 key 内至少有一个非空列表,那么弹出遇到的第一个非空列表的头元素,并和被弹出元素所属的列表的名字一起,组成结果返回给调用者。
-- 当存在多个给定 key 时, BLPOP 按给定 key 参数排列的先后顺序,依次检查各个列表。
-- 假设现在有 job 、 command 和 request 三个列表,其中 job 不存在, command 和 request 都持有非空列表。考虑以下命令:
-- LPOP job command request 0
-- BLPOP 保证返回的元素来自 command ,因为它是按”查找 job -> 查找 command -> 查找 request “这样的顺序,第一个找到的非空列表。

RPOPLPUSH

RPOPLPUSH source destination
-- 命令 RPOPLPUSH 在一个原子时间内,执行以下两个动作:
-- 将列表 source 中的最后一个元素(尾元素)弹出,并返回给客户端。
-- 将 source 弹出的元素插入到列表 destination ,作为 destination 列表的的头元素。
-- 举个例子,你有两个列表 source 和 destination , source 列表有元素 a, b, c , destination 列表有元素 x, y, z ,执行 RPOPLPUSH source destination 之后, source 列表包含元素 a, b , destination 列表包含元素 c, x, y, z ,并且元素 c 会被返回给客户端。
-- 如果 source 不存在,值 nil 被返回,并且不执行其他动作。
-- 如果 source 和 destination 相同,则列表中的表尾元素被移动到表头,并返回该元素,可以把这种特殊情况视作列表的旋转(rotation)操作。

-- 返回值:被弹出的元素

-- source 和 destination 不同
redis> LRANGE alpha 0 -1         -- 查看所有元素
1) "a"
2) "b"
3) "c"
4) "d"

redis> RPOPLPUSH alpha reciver
"d"

redis> LRANGE alpha 0 -1
1) "a"
2) "b"
3) "c"

redis> LRANGE reciver 0 -1
1) "d"

redis> RPOPLPUSH alpha reciver   -- 再执行一次,证实 RPOP 和 LPUSH 的位置正确
"c"

redis> LRANGE alpha 0 -1
1) "a"
2) "b"

redis> LRANGE reciver 0 -1
1) "c"
2) "d"


-- source 和 destination 相同
redis> LRANGE number 0 -1
1) "1"
2) "2"
3) "3"
4) "4"

redis> RPOPLPUSH number number
"4"

redis> LRANGE number 0 -1           -- 4 被旋转到了表头
1) "4"
2) "1"
3) "2"
4) "3"

redis> RPOPLPUSH number number
"3"

redis> LRANGE number 0 -1           -- 这次是 3 被旋转到了表头
1) "3"
2) "4"
3) "1"
4) "2"

LINDEX

LINDEX key index
-- 返回列表 key 中,下标为 index 的元素。
-- 下标(index)参数 start 和 stop 都以 0 为底,也就是说,以 0 表示列表的第一个元素,以 1 表示列表的第二个元素,以此类推。
-- 你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。
-- 如果 key 不是列表类型,返回一个错误。

-- 返回值:
-- 列表中下标为 index 的元素。
-- 如果 index 参数的值不在列表的区间范围内(out of range),返回 nil 。

redis> LPUSH mylist "World"
(integer) 1

redis> LPUSH mylist "Hello"
(integer) 2

redis> LINDEX mylist 0
"Hello"

redis> LINDEX mylist -1
"World"

redis> LINDEX mylist 3        -- index不在 mylist 的区间范围内
(nil)

LLEN

LLEN key
-- 返回列表 key 的长度。
-- 如果 key 不存在,则 key 被解释为一个空列表,返回 0 .
-- 如果 key 不是列表类型,返回一个错误。

-- 返回值:列表 key 的长度。

LRANGE

LRANGE key start stop
-- 返回列表 key 中指定区间内的元素,区间以偏移量 start 和 stop 指定。
-- 下标(index)参数 start 和 stop 都以 0 为底,也就是说,以 0 表示列表的第一个元素,以 1 表示列表的第二个元素,以此类推。
-- 你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。

-- 超出范围的下标
-- 超出范围的下标值不会引起错误。
-- 如果 start 下标比列表的最大下标 end ( LLEN list 减去 1 )还要大,那么 LRANGE 返回一个空列表。
-- 如果 stop 下标比 end 下标还要大,Redis将 stop 的值设置为 end 。

-- 返回值:一个列表,包含指定区间内的元素。

redis> RPUSH fp-language lisp
(integer) 1

redis> LRANGE fp-language 0 0
1) "lisp"

redis> RPUSH fp-language scheme
(integer) 2

redis> LRANGE fp-language 0 1
1) "lisp"
2) "scheme"

LREM

LREM key count value
-- 根据参数 count 的值,移除列表中与参数 value 相等的元素。
-- count 的值可以是以下几种:
-- count > 0 : 从表头开始向表尾搜索,移除与 value 相等的元素,数量为 count 。
-- count < 0 : 从表尾开始向表头搜索,移除与 value 相等的元素,数量为 count 的绝对值。
-- count = 0 : 移除表中所有与 value 相等的值。

-- 返回值:
-- 被移除元素的数量。
-- 因为不存在的 key 被视作空表(empty list),所以当 key 不存在时, LREM 命令总是返回 0 。

-- 先创建一个表,内容排列是
-- morning hello morning helllo morning
redis> LPUSH greet "morning"
(integer) 1
redis> LPUSH greet "hello"
(integer) 2
redis> LPUSH greet "morning"
(integer) 3
redis> LPUSH greet "hello"
(integer) 4
redis> LPUSH greet "morning"
(integer) 5

redis> LRANGE greet 0 4         -- 查看所有元素
1) "morning"
2) "hello"
3) "morning"
4) "hello"
5) "morning"

redis> LREM greet 2 morning     -- 移除从表头到表尾,最先发现的两个 morning
(integer) 2                     -- 两个元素被移除

redis> LLEN greet               -- 还剩 3 个元素
(integer) 3

redis> LRANGE greet 0 2
1) "hello"
2) "hello"
3) "morning"

redis> LREM greet -1 morning    -- 移除从表尾到表头,第一个 morning
(integer) 1

redis> LLEN greet               -- 剩下两个元素
(integer) 2

redis> LRANGE greet 0 1
1) "hello"
2) "hello"

redis> LREM greet 0 hello      -- 移除表中所有 hello
(integer) 2                    -- 两个 hello 被移除

redis> LLEN greet
(integer) 0

LSET

LSET key index value
-- 将列表 key 下标为 index 的元素的值设置为 value 。
-- 当 index 参数超出范围,或对一个空列表( key 不存在)进行 LSET 时,返回一个错误。

-- 返回值:操作成功返回 ok ,否则返回错误信息。

LTRIM

LTRIM key start stop
-- 对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。
-- 举个例子,执行命令 LTRIM list 0 2 ,表示只保留列表 list 的前三个元素,其余元素全部删除。
-- 下标(index)参数 start 和 stop 都以 0 为底,也就是说,以 0 表示列表的第一个元素,以 1 表示列表的第二个元素,以此类推。
-- 你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。
-- 当 key 不是列表类型时,返回一个错误。

-- 返回值:命令执行成功时,返回 ok 。

GEO

GEO数据类型支持便捷的geo地理位置计算

geoadd

-- 添加地理位置的坐标。

-- 将给定的空间元素(纬度、经度、名字)添加到指定的键里面。 这些数据会以有序集合的形式被储存在键里面, 从而使得像 GEORADIUS 和 GEORADIUSBYMEMBER 这样的命令可以在之后通过位置查询取得这些元素。 

redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
redis> GEODIST Sicily Palermo Catania
"166274.15156960039"
redis> GEORADIUS Sicily 15 37 100 km
1) "Catania"
redis> GEORADIUS Sicily 15 37 200 km
1) "Palermo"
2) "Catania"

geopos

-- 获取地理位置的坐标。

-- 从键里面返回所有给定位置元素的位置(经度和纬度)。
-- 因为 GEOPOS 命令接受可变数量的位置元素作为输入, 所以即使用户只给定了一个位置元素, 命令也会返回数组回复。

redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2

redis> GEOPOS Sicily Palermo Catania NonExisting
1) 1) "13.361389338970184"
   2) "38.115556395496299"
2) 1) "15.087267458438873"
   2) "37.50266842333162"
3) (nil)

geodist

-- 计算两个位置之间的距离。

-- 返回两个给定位置之间的距离。
-- 如果两个位置之间的其中一个不存在, 那么命令返回空值。
-- 指定单位的参数 unit 必须是以下单位的其中一个:
-- m 表示单位为米。
-- km 表示单位为千米。
-- mi 表示单位为英里。
-- ft 表示单位为英尺。
-- 如果用户没有显式地指定单位参数, 那么 GEODIST 默认使用米作为单位。
-- GEODIST 命令在计算距离时会假设地球为完美的球形, 在极限情况下, 这一假设最大会造成 0.5% 的误差。

redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2

redis> GEODIST Sicily Palermo Catania
"166274.15156960039"

redis> GEODIST Sicily Palermo Catania km
"166.27415156960038"

redis> GEODIST Sicily Palermo Catania mi
"103.31822459492736"

redis> GEODIST Sicily Foo Bar
(nil)

georadius

-- 根据用户给定的经纬度坐标来获取指定范围内的地理位置集合。

-- 以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。
-- 范围可以使用以下其中一个单位:
-- m 表示单位为米。
-- km 表示单位为千米。
-- mi 表示单位为英里。
-- ft 表示单位为英尺。
-- 在给定以下可选项时, 命令会返回额外的信息:
-- WITHDIST : 在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。 距离的单位和用户给定的范围单位保持一致。
-- WITHCOORD : 将位置元素的经度和维度也一并返回。
-- WITHHASH : 以 52 位有符号整数的形式, 返回位置元素经过原始 geohash 编码的有序集合分值。 这个选项主要用于底层应用或者调试, 实际中的作用并不大。

redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2

redis> GEORADIUS Sicily 15 37 200 km WITHDIST
1) 1) "Palermo"
   2) "190.4424"
2) 1) "Catania"
   2) "56.4413"

redis> GEORADIUS Sicily 15 37 200 km WITHCOORD
1) 1) "Palermo"
   2) 1) "13.361389338970184"
      2) "38.115556395496299"
2) 1) "Catania"
   2) 1) "15.087267458438873"
      2) "37.50266842333162"

redis> GEORADIUS Sicily 15 37 200 km WITHDIST WITHCOORD
1) 1) "Palermo"
   2) "190.4424"
   3) 1) "13.361389338970184"
      2) "38.115556395496299"
2) 1) "Catania"
   2) "56.4413"
   3) 1) "15.087267458438873"
      2) "37.50266842333162"

georadiusbymember

-- 根据储存在位置集合里面的某个地点获取指定范围内的地理位置集合。

-- 这个命令和 GEORADIUS 命令一样, 都可以找出位于指定范围内的元素, 但是 GEORADIUSBYMEMBER 的中心点是由给定的位置元素决定的, 而不是像 GEORADIUS 那样, 使用输入的经度和纬度来决定中心点。

redis> GEOADD Sicily 13.583333 37.316667 "Agrigento"
(integer) 1

redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2

redis> GEORADIUSBYMEMBER Sicily Agrigento 100 km
1) "Agrigento"
2) "Palermo"

geohash

-- 返回一个或多个位置对象的 geohash 值。

-- 返回一个或多个位置元素的 Geohash 表示。
-- 返回值
-- 一个数组, 数组的每个项都是一个 geohash 。 命令返回的 geohash 的位置与用户给定的位置元素的位置一一对应。

redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2

redis> GEOHASH Sicily Palermo Catania
1) "sqc8b49rny0"
2) "sqdtr74hyu0"

BitMap

位图(也称为位数组或位向量)是由比特位(bit)组成的数组。redis 中的位图并不是一种新的数据类型,它实际的底层数据类型是字符串。因为字符串本质上是二进制大对象(BLOB,BinaryLarge OBject ),所以可以将其视做位图。同时,因为位图存储的是布尔信息,所以在某些情况下可以节省大量的内存空间。

对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit)。
位的设置或清除取决于 value 参数,可以是 0 也可以是 1 。
当 key 不存在时,自动生成一个新的字符串值。
字符串会进行伸展(grown)以确保它可以将 value 保存在指定的偏移量上。当字符串值进行伸展时,空白位置以 0 填充。

SETBIT key offset value

redis> SETBIT bit 10086 1
(integer) 0

redis> GETBIT bit 10086
(integer) 1

redis> GETBIT bit 100   # bit 默认被初始化为 0
(integer) 0

GETBIT

-- 对 key 所储存的字符串值,获取指定偏移量上的位(bit)。
-- 当 offset 比字符串值的长度大,或者 key 不存在时,返回 0 。

-- 对不存在的 key 或者不存在的 offset 进行 GETBIT, 返回 0
redis> EXISTS bit
(integer) 0

redis> GETBIT bit 10086
(integer) 0

-- 对已存在的 offset 进行 GETBIT
redis> SETBIT bit 10086 1
(integer) 0

redis> GETBIT bit 10086
(integer) 1

BITCOUNT

-- 计算给定字符串中,被设置为 1 的比特位的数量。
-- 一般情况下,给定的整个字符串都会被进行计数,通过指定额外的 start 或 end 参数,可以让计数只在特定的位上进行。
-- start 和 end 参数的设置和 GETRANGE key start end 命令类似,都可以使用负数值: 比如 -1 表示最后一个字节, -2 表示倒数第二个字节,以此类推。
-- 不存在的 key 被当成是空字符串来处理,因此对一个不存在的 key 进行 BITCOUNT 操作,结果为 0 
-- 返回值: 被设置为 1 的位的数量。

redis> BITCOUNT bits
(integer) 0

redis> SETBIT bits 0 1          -- 0001
(integer) 0

redis> BITCOUNT bits
(integer) 1

redis> SETBIT bits 3 1          -- 1001
(integer) 0

redis> BITCOUNT bits
(integer) 2

HyperLogLog

HyperLogLog算法介绍

基数计数(cardinality counting) 通常用来统计一个集合中不重复的元素个数,例如统计某个网站的UV,或者用户搜索网站的关键词数量。数据分析、网络监控及数据库优化等领域都会涉及到基数计数的需求。
要实现基数计数,最简单的做法是记录集合中所有不重复的元素集合,当新来一个元素,若集合中不包含元素,则将加入,否则不加入,计数值就是的元素数量。这种做法存在两个问题:

  1. 当统计的数据量变大时,相应的存储内存也会线性增长
  2. 当集合变大,判断其是否包含新加入元素的成本变大

在redis 中,如果我们不需要获取数据集的内容,而只是想得到不同值的个数,那么就可以使用HyperLogLog( HLL)数据类型来优化使用集合类型时存在的内存和性能问题。

-- 用法示例
doitedu03:6379> PFADD HN:CS abc
(integer) 1
doitedu03:6379> PFADD HN:CS bbb
(integer) 1
doitedu03:6379> PFADD HN:CS ccc
(integer) 1
doitedu03:6379> PFADD HN:CS bbc
(integer) 1
doitedu03:6379> PFADD HN:CS bbc
(integer) 0
doitedu03:6379> PFCOUNT HN:CS
(integer) 4
 
doitedu03:6379> PFADD HN:ZZ bbb
(integer) 1
doitedu03:6379> PFADD HN:ZZ ccc
(integer) 1
doitedu03:6379> PFADD HN:ZZ ddd
(integer) 1
doitedu03:6379> PFADD HN:ZZ eee
(integer) 1
doitedu03:6379> PFCOUNT HN:ZZ
(integer) 4
 
doitedu03:6379> PFMERGE HN HN:ZZ HN:CS
OK
doitedu03:6379> PFCOUNT HN
(integer) 6

redis中的Hyperloglog

redis使用16384个分桶来实现HLL结构,使标准误差达到0.8125%。
redis使用的散列函数具有64位输出,这意味着它使用前14位来寻找“桶”,剩下的50位用于计算右边的0的数量。正如我们之前看到的,每个存储子集将存储最大的“连0数”,最大可能为50(因为散列中只有50个剩余位可以是0),每个存储子集需要6位才能能够存储最多50个(二进制为110010)。因此我们得到98304个bit来存储1个HLL结构;如果我们将这些bit转换为byte,我们得到6*16384/8 = 12288个byte(或12kb)这就是hyperloglog在redis实现占用的空间大小。

Redis数据持久化

Redis是基于内存的,如果不想办法将数据保存在硬盘上,一旦Redis重启(退出/故障),内存的数据将会全部丢失。(业务库中缓存的数据 , 存储的一些重要的标签, 状态数据)
我们肯定不想Redis里头的数据由于某些故障全部丢失(导致所有请求都走MySQL),即便发生了故障也希望可以将Redis原有的数据恢复过来,这就是持久化的作用。
Redis提供了两种不同的持久化方法来将数据存储到硬盘里边:
• RDB(基于快照),将某一时刻的内存中的所有数据保存到一个RDB文件中(二进制带压缩)
• AOF(append-only-file),当Redis服务器执行写命令的时候,将执行的写命令保存到AOF文件中。

RDB(快照持久化)

RDB持久化可以手动执行,也可以根据服务器配置定期执行。RDB持久化所生成的RDB文件是一个经过压缩的二进制文件,Redis可以通过这个文件还原数据库的数据。
有两个命令可以生成RDB文件:
• SAVE会阻塞Redis服务器进程,服务器不能接收任何请求,直到RDB文件创建完毕为止
• BGSAVE创建(fork)出一个子进程,由子进程来负责创建RDB文件,服务器进程可以继续接收请求。
Redis服务器在启动的时候,如果发现有RDB文件,就会自动载入RDB文件(不需要人工干预)
服务器在载入RDB文件期间,会处于阻塞状态,直到载入工作完成。
除了手动调用SAVE或者BGSAVE命令生成RDB文件之外,我们可以使用配置的方式来定期执行:
在默认的配置下,如果以下的条件被触发,就会执行BGSAVE命令

----------rdb快照------------
save 3600 1      前面是时间   后面是操作次数
save 300 10
save 60 10000

stop-writes-on-bgsave-error yes  
当启用了RDB且最后一次后台保存数据失败,Redis是否停止接收数据
rdbcompression yes  
对于存储到磁盘中的快照,可以设置是否进行压缩存储。      
如果是的话,redis会采用LZF算法进行压缩。
如果你不想消耗CPU来进行压缩的话,可以设置为关闭此功能,但是存储在磁盘上的快照会比较大。  
rdbchecksum yes
默认值是yes。在存储快照后,我们还可以让redis使用CRC64算法来进行数据校验,
但是这样做会增加大约10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能。  
dbfilename dump.rdb
设置快照的文件名,默认是 dump.rdb  
dir ./
设置快照文件的存放路径,这个配置项一定是个目录,而不能是文件名。
使用上面的 dbfilename 作为保存的文件名。

手动触发持久化

save
# 会阻塞 在保存dump.rdb文件完成之前,不能在客户端做任何的操作
bgsave
# 后台取保存 在后台开一个线程,单独的为你保存dump.rdb这个文件
CONFIG GET dir
# 数据恢复只需要将指定的dump.rdb文件导入到安装目录下即可

AOF(文件追加)

上面已经介绍了RDB持久化是通过将某一时刻数据库的数据“快照”来实现的,下面我们来看看AOF是怎么实现的。

APPEND ONLY MODE
appendonly no
# 默认该模式关闭

appendfilename "appendonly.aof"
# aof文件名,默认是"appendonly.aof"

# appendfsync always
appendfsync everysec
# appendfsync no
# aof持久化策略的配置;
# no表示不执行fsync,由操作系统保证数据同步到磁盘,速度最快;
# always表示每次写入都执行fsync,以保证数据同步到磁盘; 最多丢一条数据
# everysec表示每秒执行一次fsync,可能会导致丢失这1s数据

no-appendfsync-on-rewrite:
# 在aof重写或者写入rdb文件的时候,会执行大量IO,此时对于everysec和always的aof模式来说,
# 执行fsync会造成阻塞过长时间,no-appendfsync-on-rewrite字段设置为默认设置为no。
# 如果对延迟要求很高的应用,这个字段可以设置为yes,否则还是设置为no,
# 这样对持久化特性来说这是更安全的选择。
# 设置为yes表示rewrite期间对新写操作不fsync,暂时存在内存中,等rewrite完成后再写入,
# 默认为no,建议yes。Linux的默认fsync策略是30秒。可能丢失30秒数据。默认值为no。

auto-aof-rewrite-percentage 100
# 默认值为100。aof自动重写配置,当目前aof文件大小超过上一次重写的aof文件大小的百分之多少
# 进行重写,即当aof文件增长到一定大小的时候,Redis能够调用bgrewriteaof对日志文件进行重写。
# 当前AOF文件大小是上次日志重写得到AOF文件大小的二倍(设置为100)时,自动启动新的日志重写过程。

auto-aof-rewrite-min-size 64mb
# 设置允许重写的最小aof文件大小,避免了达到约定百分比但尺寸仍然很小的情况还要重写。

aof-load-truncated yes
# aof文件可能在尾部是不完整的,当redis启动的时候,aof文件的数据被载入内存。
# 重启可能发生在redis所在的主机操作系统宕机后,尤其在ext4文件系统没有加上data=ordered选项,
# 出现这种现象  redis宕机或者异常终止不会造成尾部不完整现象,可以选择让redis退出,或者导入尽可能多的数据。
# 如果选择的是yes,当截断的aof文件被导入的时候,会自动发布一个log给客户端然后load。
# 如果是no,用户必须手动redis-check-aof修复AOF文件才可以。默认值为 yes。

AOF重写(BGREWRITEAOF命令)

-- 数据库经历了如下操作
set a 1
set a 2
set a 3
set a 4
set a 5
set a 6
set a 7
set a 8
-- 那么,aof中的记录也会有上述的8条
-- 然而,数据库中的最终状态仅仅是:  a  -> 8
-- 那么,aof中的大量记录都是冗余无效的,可以执行rewrite操作来精简体积提高效率
==>  rewrite aof
set a 8
-- 可以通过配置让redis自动定期对aof文件进行重写
-- 也可以用命令来触发aof重写:  BGREWRITEAOF

持久化方式的选择

RDB和AOF并不互斥,它俩可以同时使用。

  • RDB的优点:载入时恢复数据快、文件体积小。
  • RDB的缺点:会一定程度上丢失数据(因为系统一旦在定时持久化之前出现宕机现象,此前没有来得及写入磁盘的数据都将丢失。)
  • AOF的优点:丢失数据少(默认配置只丢失一秒的数据)。
  • AOF的缺点:恢复数据相对较慢,文件体积大

如果Redis服务器同时开启了RDB和AOF持久化,服务器会优先使用AOF文件来还原数据(因为AOF更新频率比RDB更新频率要高,还原的数据更完善)

posted @ 2023-06-04 21:28  _泡泡  阅读(48)  评论(0编辑  收藏  举报