1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#启动相关
/////////////////////////////////////////////////////////////////////

# 开启 redis-server 是隐形的开启
$ sudo service redis-server start

# 开启 redis-server 是显式的开启
$ redis-server

# 进入 redis-cli
$ redis-cli

# 可在客户端中关闭redis服务
> shutdown

#查看 Redis 在命令行终端执行如下命令查看 Redis:
$ ps -ef | grep redis

#通过端口号检查 Redis 服务器状态:
netstat -nlt| grep 6379

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#数据类型
/////////////////////////////////////////////////////////////////////
# string

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

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

# 加法器默认 +1
> incr 我的键

# 加法器 自定义计数 (比如下面加50)
> incrby 我的键 50

# 减法器 用法参考加法器
> decr
> decrby

#追加值中的字符串(完成字符串拼接)
append mykey aaaaa

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

# 获取所有 键
> keys *

/////////////////////////////////////////////////////////////////////
# List

# 链表类型的值 rpush是尾插法 lpush是头插法
> rpush mylist A
> rpush mylist B
> lpush mylist first
# 这些命令都是可变的命令,也就是说你可以一次加入多个元素放入 list:
> rpush mylist 1 2 3 4 5 "foo bar"

# lrange 遍历 需要两个索引,0 表示 list 开头第一个,-1 表示 list 的倒数第一个,即最后一个。-2 则是 list 的倒数第二个,以此类推。
> lrange mylist 0 -1

# 删除 键和对应的值
> del mylist

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

# Redis 提供了阻塞式访问 brpop 和 blpop 命令。用户可以在获取数据不存在时阻塞请求队列,如果在时限内获得数据则立即返回,如果超时还没有数据则返回 nil。
# List阻塞操作 (下面两个是代表阻塞等待10s,如果10s后还没有数据到达,就解除阻塞并返回nil)
> brpop mylist 10
> blpop mylist 10

# 获取链表的长度(元素个数)
> llen mylist

/////////////////////////////////////////////////////////////////////
#hashes

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

# hset 命令设置一个哈希键 对应一个键值对(字段)
> hset user birthyear 1988

# hmset 命令设置一个多域的 hash 表 (一个哈希键,对应多个键值对字段)
> hmset user username antirez birthyear 1977 verified 1

# hget 命令获取指定的单域
> hget user username
> hget user birthyear

# hgetall 命令获取指定 key 的所有信息
> hgetall user

#hmget 类似于 hget
> hmget user username birthyear aaa


#同样可以根据需要对 hash 表的表项进行单独的操作
#这里做了加法器
> hincrby user birthyear 10

/////////////////////////////////////////////////////////////////////
# 无序 Set

# sadd 命令产生一个无序集合,返回集合的元素个数。
> sadd myset 1 2 3

# smembers 用于查看集合。
> smembers myset

#sismember 用于查看集合是否存在,匹配项包括集合名和元素(用于查看该元素是否是集合的成员)。匹配成功返回 1,匹配失败返回 0。
> sismember myset 3
> sismember myset 30
> sismember mys 3

#实际做项目就是求交集,并集,差集之类的,比如共同好友之类的
> sdiff A B #差集 集合A - 集合B
> sinter A B #交集 集合A ∩ 集合B
> sunion A B #并集 集合A ∪ 集合B

/////////////////////////////////////////////////////////////////////
# 有序 Set (SortSet)

# zadd 与 sadd 类似,但是在元素之前多了一个参数,这个参数便是用于排序的。形成一个有序的集合。
> zadd myset 1940 "Alan Kay"
> zadd myset 1957 "asdfasdf"
> zadd myset 20 "bbbbbb"

# 从小到大(正序查看集合内容)
> zrange myset 0 -1
# 从大到小(反序查看集合内容)
> zrevrange myset 0 -1

# 带返回权值地查看 withscores
> zrange myset 0 -1 withscores # 从小到大(正序查看集合内容)
> zrevrange myset 0 -1 withscores # 从大到小(反序查看集合内容)


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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# redis系统管理
///////////////////////////////////////////////////////////////////
#适合全体类型的常用命令

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

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

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

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

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

# 清除界面。
> clear

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

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

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

///////////////////////////////////////////////////////////////////
# redis时间相关命令

# 限定 key 生存时间,这同样是一个无视数据类型的命令,对于临时存储很有用处。避免进行大量的 DEL 操作。
# 设置某个 key 的过期时间(秒),比如:expire bruce 1000 表示设置 bruce 这个 key 1000 秒后系统自动删除.
> expire key 10

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

# 查找某个 key 还有多长时间过期,返回时间单位为秒。(返回-1为没有定义过限时,返回-2是定义过限时,时间到了)
> ttl key

# 生存时间也可以取消
> persist key

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

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

# 把生存时间单位改为毫秒
> pexpire key milliseconds

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

# 用来读取运行 Redis 服务器的配置参数。
> config get
# 用于更改运行 Redis 服务器的配置参数。
> config set
# 认证密码。(进入客户端后的做法)
> auth 密码

# 例如:
> config get requirepass # 查看密码
> config set requirepass test123 # 设置密码为 test123
> config get requirepass # 报错,没有认证
> auth test123 # 认证密码
> config get requirepass
#可以通过修改 Redis 的配置文件 redis.conf 修改密码。


# 认证密码。(进入客户端前的做法)
> redis-cli -a mima


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

#结果如下
1) "hash-max-ziplist-entries"
2) "512"
3) "list-max-ziplist-entries"
4) "512"
5) "set-max-intset-entries"
6) "512"
7) "zset-max-ziplist-entries"
8) "128"

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

/////////////////////////////////////////////////////////////////////
# 查询 Redis 相关信息。
> info

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

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

# 例如:
> info keyspace
> info server
> info
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# Redis高级应用
/////////////////////////////////////////////////////////////////////
# 主从复制
为了分担服务器压力,会在特定情况下部署多台服务器分别用于缓存的读和写操作,用于写操作的服务器称为主服务器,用于读操作的服务器称为从服务器。

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


Redis 主从复制的过程:

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

可以拥有多个 Slave。
多个 Slave 可以连接同一个 Master 外,还可以连接到其它的 Slave。(当 Master 宕机后,相连的 Slave 转变为 Master)。
主从复制不会阻塞 Master,在同步数据时, Master 可以继续处理 Client 请求。
提高了系统的可伸缩性。
从服务器的主要作用是响应客户端的数据请求,比如返回一篇博客信息。

上面说到了主从复制是不会阻塞 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 的版本要求。

/////////////////////////////////////////////////////////////////////
# 事务处理 (不如mysql)

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

> multi
> set name a
> set name b
> exec
> get name

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

/////////////////////////////////////////////////////////////////////
# 持久化机制

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

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

Redis 支持两种持久化方式:

1、snapshotting(快照):将数据存放到文件里,默认方式。 是将内存中的数据以快照的方式写入到二进制文件中,默认文件 dump.rdb,可以通过配置设置自动做快照持久化的方式。可配置 Redis 在 n 秒内如果超过 m 个 key 被修改就自动保存快照。比如: save 900 1:900 秒内如果超过 1 个 key 被修改,则发起快照保存。 save 300 10:300 秒内如果超过 10 个 key 被修改,则快照保存。 2、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 命令是将数据写入磁盘中。

> help save
> save

/////////////////////////////////////////////////////////////////////
# 虚拟内存的使用

虚拟内存管理在 2.6 及之上版本取消了,取消了是指这部分内容在后面的版本会由 redis 软件自身管理。在本实验中,选择的是 4.0.9 版本的 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