0%

Redis学习笔记

实验楼练习地址:Redis基础教程,本文拷贝自实验楼

Redis简介

Redis 是什么

REmote DIctionary Server(Redis) 是一个由 Salvatore Sanfilippo 写的 key-value 存储系统。Redis 提供了一些丰富的数据结构,包括 lists、sets、ordered sets 以及 hashes ,当然还有和 Memcached 一样的 strings 结构。Redis 当然还包括了对这些数据结构的丰富操作。

Redis 常被称作是一款数据结构服务器(data structure server)。Redis 的键值可以包括字符串(strings)类型,同时它还包括哈希(hashes)、列表(lists)、集合(sets)和 有序集合(sorted sets)等数据类型。

对于这些数据类型,你可以执行原子操作。例如:对字符串进行附加操作(append);递增哈希中的值;向列表中增加元素;计算集合的交集、并集与差集等。

Redis 的优点

性能极高:Redis 能支持超过 100K+ 每秒的读写频率。
丰富的数据类型:Redis 支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
原子:Redis 的所有操作都是原子性的,同时 Redis 还支持对几个操作全并后的原子性执行。
丰富的特性:Redis 还支持 publish/subscribe, 通知, key 过期等等特性。

Redis的安装

使用 Redis 只需要下载对应的软件包开箱即用,截止目前(2019.1)最新的版本有 5.* 可用,实验楼提供的是 2.8.4 稳定版,这也是目前市场的主流版本。

使用通用的源码包进行编译安装。

下载 Redis 的程序包:

wget http://labfile.oss.aliyuncs.com/courses/106/redis-2.8.4.tar.gz
tar -xzvf redis-2.8.4.tar.gz
cd redis-2.8.4
make
make test

服务端:src/redis-server
客户端:src/redis-cli
默认配置文件:redis.conf
cp redis-server /usr/local/bin/
cp redis-cli /usr/local/bin/

添加完成后在任何目录下输入 redis-server 可启动服务器,输入 redis-cli 可启动客户端。

Pacman

在ArchLinux下用Pacman安装,版本号已经达到5.x,可一键安装服务器和客户端 sudo pacman -S redis,以守护进程启动 sudo systemctl start redis,启动客户端和上述方法一样。配置 /etc/redis.conf

Redis启动

服务端通用的启动方法是 redis-server,默认占用6379端口,可以在启动时指定具体的配置文件,查看进程:pe -ef|grep redis

客户端启动方法为 redis-cli,在有的环境下,redis 交互环境可能出现中文乱码的情况,解决办法是用下列命令启动 redis 客户端 redis-cli --raw

Redis数据类型

Redis 不仅仅是简单的 key-value 存储器,同时也是一种 data structures server。传统的 key-value 是指支持使用一个 key 字符串来索引 value 字符串的存储,而 Redis 中,value 不仅仅支持字符串,还支持更多的复杂结构,包括列表、集合、哈希表等。

Strings

字符串是一种最基本、最常用的 Redis 值类型。

Redis 字符串是二进制安全的,这意味着一个 Redis 字符串能包含任意类型的数据,例如: 一张经过 base64 编码的图片或者一个序列化的 Ruby 对象。通过这样的方式,Redis 的字符串可以支持任意形式的数据,但是对于过大的文件不适合存入 redis,一方面系统内存有限,另外一方面字符串类型的值最多能存储 512M 字节的内容。

可以使用 set 和 get 命令来创建和检索 strings。注意:set 命令将取代现有的任何已经存在的 key

127.0.0.1:6379> set mykey myvalue
OK
127.0.0.1:6379> get mykey
"myvalue"

set 命令还有一个提供附加参数的选项,我们能够让 set 命令只有在没有相同 key 的情况下成功,反之亦然,可以让 set 命令在有相同 key 值的情况下成功:
127.0.0.1:6379> set mykey newval nx
(nil)
127.0.0.1:6379> set mykey newval xx
OK

对string类型数据的加法,自增:

127.0.0.1:6379> set counter 100 #初始化counter 100
OK
127.0.0.1:6379> incr counter #counter +1
(integer) 101
127.0.0.1:6379> incrby counter 50 #counter +50
(integer) 151

counter始终是字符串对象,但是字面量必须是整数才能适用加法自增。

Redis 可以运用 mset 和 mget 命令一次性完成多个 key-value 的对应关系,使用 mget 命令,Redis 返回一个 value 数组:

127.0.0.1:6379> mset a 10 b 20 c 30
OK
127.0.0.1:6379> mget a b c
1) "10"
2) "20"
3) "30"

Lists

Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边),lpush 命令插入一个新的元素到头部,而 rpush 命令插入一个新元素到尾部。当这两个操作中的任一操作在一个空的 Key 上执行时就会创建一个新的列表。相似的,如果一个列表操作清空一个列表,那么对应的 key 将被从 key 空间删除。

push 一类的命令的返回值为 list 的长度。这里有一些类表操作和结果的例子:

127.0.0.1:6379> rpush mylist A #如果mylist不存在,会自主创建初始化第一个元素为A
(integer) 1
127.0.0.1:6379> rpush mylist B
(integer) 2
127.0.0.1:6379> rpush mylist 0
(integer) 3
127.0.0.1:6379> lrange mylist 0 -1 #0 -1表示按照序号从左到右,-1表示最后一个,用于展示全部
1) "A"
2) "B"
3) "0"

这些命令都是可变的命令,也就是说你可以一次加入多个元素放入 list:
127.0.0.1:6379> rpush mylist 1 2 3 4 5 "foo bar"
(integer) 9
127.0.0.1:6379> lrange mylist 0 -1
1) "A"
2) "B"
3) "0"
4) "1"
5) "2"
6) "3"
7) "4"
8) "5"
9) "foo bar"

在 Redis 的命令操作中,还有一类重要的操作:pop,它可以弹出一个元素,简单的理解就是获取并删除第一个元素,和 push 类似的是它也支持双边的操作,可以从右边弹出一个元素也可以从左边弹出一个元素,对应的指令为 rpop 和 lpop:

127.0.0.1:6379> del mylist #删除 初始化列表
(integer) 1
127.0.0.1:6379> rpush mylist a b c
(integer) 3
127.0.0.1:6379> rpop mylist
"c"
127.0.0.1:6379> lrange mylist 0 -1
1) "a"
2) "b"
127.0.0.1:6379> lpop mylist
"a"
127.0.0.1:6379> lrange mylist 0 -1
1) "b"

一个列表最多可以包含 4294967295(2 的 32 次方减一) 个元素,这意味着它可以容纳海量的信息,最终瓶颈一般都取决于服务器内存大小。

事实上,在高级的企业架构当中,会把缓存服务器分离开来,因为数据库服务器和缓存服务器的特点各异,比如对于数据库服务器应该用更快、更大的硬盘,而缓存专用服务器则偏向内存性能,一般都是 64GB 起步。

List 阻塞操作

理解阻塞操作对一些请求操作有很大的帮助,关于阻塞操作的作用,这里举一个例子。

假如你要去楼下买一个汉堡,一个汉堡需要花一定的时间才能做出来,非阻塞式的做法是去付完钱走人,过一段时间来看一下汉堡是否做好了,没好就先离开,过一会儿再来,而且要知道可能不止你一个人在买汉堡,在你离开的时候很可能别人会取走你的汉堡,这是很让人烦的事情。

阻塞式就不一样了,付完钱一直在那儿等着,不拿到汉堡不走人,并且后面来的人统统排队。

Redis 提供了阻塞式访问 brpop 和 blpop 命令。用户可以在获取数据不存在时阻塞请求队列,如果在时限内获得数据则立即返回,如果超时还没有数据则返回 null。

List 常见应用场景

分析 List 应用场景需要结合它的特点,List 元素是线性有序的,很容易就可以联想到聊天记录,你一言我一语都有先后,因此 List 很适合用来存储聊天记录等顺序结构的数据。

Hashes

Redis Hashes 是字符串字段和字符串值之间的映射,因此它们是展现对象的完美数据类型。例如一个有名、姓、年龄等等属性的用户:一个带有一些字段的 hash 仅仅需要一块很小的空间存储,因此你可以存储数以百万计的对象在一个小的 Redis 实例中。哈希主要用来表现对象,它们有能力存储很多对象,因此你可以将哈希用于许多其它的任务。

127.0.0.1:6379> hmset user:1000 username antirez birthyear 1977 verified 1
OK
127.0.0.1:6379> hget user:1000 username
"antirez"
127.0.0.1:6379> hget user:1000 birthyear
"1977"
127.0.0.1:6379> hgetall user:1000
1) "username"
2) "antirez"
3) "birthyear"
4) "1977"
5) "verified"
6) "1"

hmset 命令设置一个多域的 hash 表,hget 命令获取指定的单域,hgetall 命令获取指定 key 的所有信息。hmget 类似于 hget,只是返回一个 value 数组。

127.0.0.1:6379> hmget user:1000 username birthyear no-such-field
1) "antirez"
2) "1977"
3) (nil)

同样可以根据需要对 hash 表的表项进行单独的操作

127.0.0.1:6379> hincrby user:1000 birthyear 10
(integer) 1987
127.0.0.1:6379> hgetall user:1000
1) "username"
2) "antirez"
3) "birthyear"
4) "1987"
5) "verified"
6) "1"

Set

Redis 集合(Set)是一个无序的字符串集合。你可以以 O(1) 的时间复杂度 (无论集合中有多少元素时间复杂度都是常量)完成添加、删除以及测试元素是否存在。

Redis 集合拥有令人满意的不允许包含相同成员的属性,多次添加相同的元素,最终在集合里只会有一个元素,这意味着它可以非常方便地对数据进行去重操作,一个 Redis 集合的非常有趣的事情是它支持一些服务端的命令从现有的集合出发去进行集合运算,因此你可以在非常短的时间内进行合并(unions), 求交集(intersections), 找出不同的元素(differences of sets)。

127.0.0.1:6379> sadd myset 1 2 3
(integer) 3
127.0.0.1:6379> smembers myset
1) "1"
2) "2"
3) "3"
127.0.0.1:6379> sismember myset 3
(integer) 1
127.0.0.1:6379> sismember myset 30
(integer) 0
127.0.0.1:6379> sismember mys 3
(integer) 0

sadd 命令产生一个无序集合,返回集合的元素个数。smembers 用于查看集。sismember 用于查看集合是否存在,匹配项包括集合名和元素个数。匹配成功返回 1,匹配失败返回 0。

sismember myset 3
sismember myset 30
sismember mys 3
操作截图:

Sorted Set

Redis 有序集合与普通集合非常相似,是一个没有重复元素的字符串集合。不同之处是有序集合的每一个成员都关联了一个权值,这个权值被用来按照从最低分到最高分的方式排序集合中的成员。集合的成员是唯一的,但是权值可以是重复的。

使用有序集合你可以以非常快的速度(O(log(N)))添加、删除和更新元素。因为元素是有序的, 所以你也可以很快的根据权值(score)或者次序(position)来获取一个范围的元素。访问有序集合的中间元素也是非常快的,因此你能够使用有序集合作为一个没有重复成员的智能列表。在有序集合中,你可以很快捷的访问一切你需要的东西:有序的元素,快速的存在性测试,快速访问集合的中间元素!简而言之使用有序集合你可以完成许多对性能有极端要求的任务,而那些任务使用其它类型的数据库真的是很难完成的。

zadd 与 sadd 类似,但是在元素之前多了一个参数,这个参数便是用于排序的。形成一个有序的集合。

zadd hackers 1940 "Alan Kay"
zadd hackers 1957 "Sophie Wilson"
zadd hackers 1953 "Richard Stallman"
zadd hackers 1949 "Anita Borg"
zadd hackers 1965 "Yukihiro Matsumoto"
zadd hackers 1914 "Hedy Lamarr"
zadd hackers 1916 "Claude Shannon"
zadd hackers 1969 "Linus Torvalds"
zadd hackers 1912 "Alan Turing"

查看集合:zrange 是查看正序的集合,zrevrange 是查看反序的集合。0 表示集合第一个元素,-1 表示集合的倒数第一个元素。

127.0.0.1:6379> zrange hackers 0 -1
1) "Alan Turing"
2) "Hedy Lamarr"
3) "Claude Shannon"
4) "Alan Kay"
5) "Anita Borg"
6) "Richard Stallman"
7) "Sophie Wilson"
8) "Yukihiro Matsumoto"
9) "Linus Torvalds"
127.0.0.1:6379> zrevrange hackers 0 -1
1) "Linus Torvalds"
2) "Yukihiro Matsumoto"
3) "Sophie Wilson"
4) "Richard Stallman"
5) "Anita Borg"
6) "Alan Kay"
7) "Claude Shannon"
8) "Hedy Lamarr"
9) "Alan Turing"

使用 withscores 参数返回记录值。

127.0.0.1:6379> zrange hackers 0 -1 withscores
1) "Alan Turing"
2) "1912"
3) "Hedy Lamarr"
4) "1914"
5) "Claude Shannon"
6) "1916"
7) "Alan Kay"
8) "1940"
9) "Anita Borg"
10) "1949"
11) "Richard Stallman"
12) "1953"
13) "Sophie Wilson"
14) "1957"
15) "Yukihiro Matsumoto"
16) "1965"
17) "Linus Torvalds"
18) "1969"

Redis系统管理

适合全体类型的常用命令

EXISTS and DEL

exists key:判断一个 key 是否存在,存在返回 1,否则返回 0。

del key:删除某个 key,或是一系列 key,比如:del key1 key2 key3 key4。成功返回 1,失败返回 0(key 值不存在)。

127.0.0.1:6379> set mykey hello
OK
127.0.0.1:6379> exists mykey
(integer) 1
127.0.0.1:6379> del mykey
(integer) 1
127.0.0.1:6379> exists mykey
(integer) 0

TYPE and KEYS

type key:返回某个 key 元素的数据类型 (none:不存在,string:字符,list:列表,set:元组,zset:有序集合,hash:哈希),key 不存在返回空。

keys key—pattern:返回匹配的 key 列表,比如:keys foo* 表示查找 foo 开头的 keys。

127.0.0.1:6379> set mykey x
OK
127.0.0.1:6379> type mykey
string
127.0.0.1:6379> keys my*
1) "mylist"
2) "mykey"
3) "myset"
127.0.0.1:6379> del mykey
(integer) 1
127.0.0.1:6379> keys my*
1) "mylist"
2) "myset"
127.0.0.1:6379> type mykey
none

RANDOMKEY and CLEAR

randomkey:随机获得一个已经存在的 key,如果当前数据库为空,则返回空字符串。

127.0.0.1:6379> randomkey
"myset"

clear 清屏

RENAME and RENAMENX

rename oldname newname:更改 key 的名字,新键如果存在将被覆盖。

renamenx oldname newname:更改 key 的名字,新键如果存在则更新失败。

127.0.0.1:6379> rename mylist newlist
OK
127.0.0.1:6379> exists mylist
(integer) 0
127.0.0.1:6379> exists newlist
(integer) 1

DBSIZE

dbsize 返回当前数据库的 key 的总数。

127.0.0.1:6379> dbsize
(integer) 8

Redis 时间相关命令

限定 key 生存时间

这同样是一个无视数据类型的命令,对于临时存储很有用处。避免进行大量的 DEL 操作。

expire:设置某个 key 的过期时间(),比如:expire bruce 1000 表示设置 bruce 这个 key 1000 秒后系统自动删除,注意:如果在还没有过期的时候,对值进行了改变,那么那个值会被清除。

127.0.0.1:6379> set key some-value
OK
127.0.0.1:6379> expire key 10
(integer) 1
127.0.0.1:6379> get key (马上执行此命令)
"some-value"
127.0.0.1:6379> get key (10s后执行此命令)
(nil)

结果显示:执行 expire 命令后,马上 get 会显示 key 存在;10 秒后再 get 时,key 已经被自动删除。

查询 key 剩余生存时间

限时操作可以在 set 命令中实现,并且可用 ttl 命令查询 key 剩余生存时间。

ttl:查找某个 key 还有多长时间过期,返回时间单位为秒。

127.0.0.1:6379> set key 100 ex 30
OK
127.0.0.1:6379> ttl key
(integer) 26
127.0.0.1:6379> ttl key
(integer) 22

清除 key

flushdb:清空当前数据库中的所有键。

flushall:清空所有数据库中的所有键。

Redis 设置相关命令

Redis 有其配置文件,可以通过 client-command 窗口查看或者更改相关配置。下面介绍相关命令。

CONFIG GET and CONFIG SET

config get :用来读取运行 Redis 服务器的配置参数。

config set:用于更改运行 Redis 服务器的配置参数。

auth:认证密码。

下面针对 Redis 密码的示例:

127.0.0.1:6379> config get requirepass  查看密码
1) "requirepass"
2) ""
127.0.0.1:6379> config set requirepass 12345 # 设置密码为12345
OK
127.0.0.1:6379> config get requirepass # 报错,没有认证
(error) NOAUTH Authentication required.
127.0.0.1:6379> auth 12345 # 认证密码
OK
127.0.0.1:6379> config get requirepass
1) "requirepass"
2) "12345"

可以通过修改 Redis 的配置文件 redis.conf 修改密码。

config get 命令是以 list 的 key-value 对显示的,如查询数据类型的最大条目:

127.0.0.1:6379> auth 12345
OK
127.0.0.1:6379> config get *max-*-entries*
1) "hash-max-ziplist-entries"
2) "512"
3) "set-max-intset-entries"
4) "512"
5) "zset-max-ziplist-entries"
6) "128"

config resetstat:重置数据统计报告,通常返回值为 “OK”。

127.0.0.1:6379> config resetstat
OK

查询信息

info [section]:查询 Redis 相关信息。

info 命令可以查询 Redis 几乎所有的信息,其命令选项有如下:

  • server: Redis server 的常规信息
  • clients: Client 的连接选项
  • memory: 存储占用相关信息
  • persistence: RDB and AOF 相关信息
  • stats: 常规统计
  • replication: Master/Slave 请求信息
  • cpu: CPU 占用信息统计
  • cluster: Redis 集群信息
  • keyspace: 数据库信息统计
  • all: 返回所有信息
  • default: 返回常规设置信息

若命令参数为空,info 命令返回所有信息。

127.0.0.1:6379> info keyspace
# Keyspace
127.0.0.1:6379> info server
# Server
redis_version:5.0.4
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:534ea8a77d5f7efc
redis_mode:standalone
os:Linux 5.0.9-arch1-1-ARCH x86_64
arch_bits:64
multiplexing_api:epoll
atomicvar_api:atomic-builtin
gcc_version:8.2.1
process_id:19050
run_id:f9d6cf4324df9d6fb6616750de1424f28bd1fd3c
tcp_port:6379
uptime_in_seconds:73127
uptime_in_days:0
hz:10
configured_hz:10
lru_clock:13020011
executable:/usr/bin/redis-server
config_file:/etc/redis.conf

Redis 的高级应用

安全性

涉及到客户端连接是需要指定密码的(由于 redis 速度相当的快,一秒钟可以 150K 次的密码尝试,所以需要设置一个强度很大的密码)。

设置密码的方式有两种:

  • 使用 config set 命令的 requirepass 参数,具体格式为 config set requirepass "password"
  • redis.conf 文件中设置 requirepass 属性,后面为密码。
    输入认证的方式也有两种:

登录时可以使用 redis-cli -a password。登录后可以使用 auth password

设置密码

第一种密码设置方式在上一个实验中已经提到(在 CONFIG SET 命令讲解的实例),此处我们来看看第二种方式设置密码。

首先需要进入 Redis 的安装目录,然后修改配置文件 redis.conf。根据 grep 命令的结果,使用 vim 编辑器修改 # requirepass foobaredrequirepass 12345,然后保存退出。

grep -n requirepass /etc/redis/redis.conf
sudo vim /etc/redis/redis.conf

重启 redis-server 与 redis-cli

重启 redis server:

sudo service redis-server restart 或者 sudo systemctl restart redis

进入到 redis-cli 交互界面进行验证:

> info
> auth 12345
> info
> exit

结果表明第一次 info 命令失败,在 auth 认证之后 info 命令正常返回,最后退出 redis-cli。

另外一种密码认证方式,启动客户端时验证:redis-cli -a 12345

主从复制

为了分担服务器压力,会在特定情况下部署多台服务器分别用于缓存的读和写操作,用于写操作的服务器称为主服务器,用于读操作的服务器称为从服务器。

从服务器通过 psync 操作同步主服务器的写操作,并按照一定的时间间隔更新主服务器上新写入的内容。

Redis 主从复制的过程:

  1. Slave 与 Master 建立连接,发送 psync 同步命令。
  2. Master 会启动一个后台进程,将数据库快照保存到文件中,同时 Master 主进程会开始收集新的写命令并缓存。
  3. 后台完成保存后,就将此文件发送给 Slave。
  4. Slave 将此文件保存到磁盘上。

Redis 主从复制特点:

  1. 可以拥有多个 Slave。
  2. 多个 Slave 可以连接同一个 Master 外,还可以连接到其它的 Slave。(当 Master 宕机后,相连的 Slave 转变为 Master)
  3. 主从复制不会阻塞 Master,在同步数据时, Master 可以继续处理 Client 请求。
  4. 提高了系统的可伸缩性。

从服务器的主要作用是响应客户端的数据请求,比如返回一篇博客信息。

上面说到了主从复制是不会阻塞 Master 的,就是说 Slave 在从 Master 复制数据时,Master 的删改插入等操作继续进行不受影响。

如果在同步过程中,主服务器修改了一篇博客,而同步到从服务器上的博客是修改前的。这时候就会出现时间差,即修改了博客过后,在访问网站的时候还是原来的数据,这是因为从服务器还未同步最新的更改,这也就意味着非阻塞式的同步只能应用于对读数据延迟接受度较高的场景。

要建立这样一个主从关系的缓存服务器,只需要在 Slave 端执行命令:

# SLAVEOF IPADDRESS:PORT
> SLAVEOF 127.0.0.1:6379

如果主服务器设置了连接密码,就需要在从服务器中事先设置好:
config set masterauth <password>

这样,当前服务器就作为 127.0.0.1:6379 下的一个从服务器,它将定期从该服务器复制数据到自身。

在以前的版本中(2.8 以前),你应该慎用 redis 的主从复制功能,因为它的同步机制效率低下,可以想象每一次短线重连都要复制主服务器上的全部数据,算上网络通讯所耗费的时间,反而可能达不到通过 redis 缓存来提升应用响应速度的效果。但是幸运的是,官方在 2.8 以后推出了解决方案,通过部分同步来解决大量的重复操作。

这需要主服务器和从服务器都至少达到 2.8 的版本要求。

事务处理

Redis 的事务处理比较简单。只能保证 client 发起的事务中的命令可以连续的执行,而且不会插入其它的 client 命令,当一个 client 在连接中发出 multi 命令时,这个连接就进入一个事务的上下文,该连接后续的命令不会执行,而是存放到一个队列中,当执行 exec 命令时,redis 会顺序的执行队列中的所有命令。

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set name a
QUEUED
127.0.0.1:6379> set name b
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
127.0.0.1:6379> get name
"b"

需要注意的是,redis 对于事务的处理方式比较特殊,它不会在事务过程中出错时恢复到之前的状态,这在实际应用中导致我们不能依赖 redis 的事务来保证数据一致性

持久化机制

内存和磁盘的区别除了速度差别以外,还有就是内存中的数据会在重启之后消失,持久化的作用就是要将这些数据长久存到磁盘中以支持长久使用。

Redis 是一个支持持久化的内存数据库,Redis 需要经常将内存中的数据同步到磁盘来保证持久化。

Redis 支持两种持久化方式:

  1. snapshotting(快照):将数据存放到文件里,默认方式。

是将内存中的数据以快照的方式写入到二进制文件中,默认文件 dump.rdb,可以通过配置设置自动做快照持久化的方式。可配置 Redis 在 n 秒内如果超过 m 个 key 被修改就自动保存快照。比如:

save 900 1:900 秒内如果超过 1 个 key 被修改,则发起快照保存。

save 300 10:300 秒内如果超过 10 个 key 被修改,则快照保存。

  1. Append-only file(缩写为 aof):将读写操作存放到文件中。

由于快照方式在一定间隔时间做一次,所以如果 Redis 意外 down 掉的话,就会丢失最后一次快照后的所有修改。

aof 比快照方式有更好的持久化性,是由于使用 aof 时,redis 会将每一个收到的写命令都通过 write 函数写入到文件中,当 redis 启动时会通过重新执行文件中保存的写命令来在内存中重新建立整个数据库的内容。

由于 os 会在内核中缓存 write 做的修改,所以可能不是立即写到磁盘上,这样 aof 方式的持久化也还是有可能会丢失一部分数据。可以通过配置文件告诉 redis 我们想要通过 fsync 函数强制 os 写入到磁盘的时机。

配置文件中的可配置参数:

appendonly yes //启用 aof 持久化方式

# appendfsync always //收到写命令就立即写入磁盘,最慢,但是保证了数据的完整持久化

appendfsync everysec //每秒钟写入磁盘一次,在性能和持久化方面做了很好的折中

# appendfsync no //完全依赖 os,性能最好,持久化没有保证

在 redis-cli 的命令中,save 命令是将数据写入磁盘中。
127.0.0.1:6379> help save

SAVE -
summary: Synchronously save the dataset to disk
since: 1.0.0
group: server

127.0.0.1:6379> save
OK

虚拟内存的使用

虚拟内存管理在 2.6 及之上版本取消了,取消了是指这部分内容在后面的版本会由 redis 软件自身管理,在本实验中,选择的是 2.8.4 版本的 redis,所以实验中的配置文件没有虚拟内存管理功能的配置选项,此处仅为讲解。

Redis 的虚拟内存是暂时把不经常访问的数据从内存交换到磁盘中,从而腾出内存空间用于其它的访问数据,尤其对于 redis 这样的内存数据库,内存总是不够用的。除了分隔到多个 redis server 外,提高数据库容量的方法就是使用虚拟内存,把那些不常访问的数据交换到磁盘上。

通过配置 vm 相关的 redis.config 配置:

# 开启 vm 功能
vm-enable yes

# 交换出来的 value 保存的文件路径
vm-swap-file /tmp/redis.swap

# redis 使用的最大内存上限
vm-max-memory 10000000

# 每个页面的大小 32 字节
vm-page-size 32

# 最多使用多少个页面
vm-pages 123217729

# 用于执行 value 对象换入的工作线程数量
vm-max-threads 4

Disqus评论区没有正常加载,请使用科学上网