【引言】作为一个开发人员,稍微有一些开发经验的话,多多少少也会听说过redis的大名,你可以把它当做缓存,也可以把它作为消息队列,它可以做很多事情,而且它的性能还很强大,所以,这里开一个专题来聊聊关于Redis的点点滴滴吧!
Redis入门
Redis是什么
[官方定义]Redis(Remote DIctionary Server) is an open source (BSD licensed), in-memory data structure store, used as a database, cache and message broker. It supports data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs and geospatial indexes with radius queries. Redis has built-in replication, Lua scripting, LRU eviction, transactions and different levels of on-disk persistence, and provides high availability via Redis Sentinel and automatic partitioning with Redis Cluster.
Redis支持的数据结构
- String: 字符串
- Hash: 散列
- List: 列表
- Set: 集合
- Sorted Set: 有序集合
Redis的几大特点
- Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
- Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
- Redis支持数据的备份,即master-slave模式的数据备份。
Redis的优势
- 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
- 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
- 原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
- 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。
- Redis运行在内存中但是可以持久化到磁盘(RDB、AOF)
Redis常用命令
基本操作
1 | # 连接 |
Redis连接
1 | - AUTH password 验证密码是否正确 |
脚本执行
1 | # Redis 脚本使用 Lua 解释器来执行脚本。 Redis 2.6 版本通过内嵌支持 Lua 环境。执行脚本的常用命令为 EVAL。 |
key常用操作
1 | - DEL key 该命令用于在 key 存在时删除 key。 |
string操作(前缀:无)
1 | - SET key value 设置指定 key 的值 |
hash操作(前缀:H)
1 | - HDEL key field1 [field2] 删除一个或多个哈希表字段 |
list操作(前缀:L、R、BL、BR)
1 | - BLPOP key1 [key2 ] timeout 移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。 |
set操作(前缀:S)
1 | - SADD key member1 [member2] 向集合添加一个或多个成员 |
sorted set操作(前缀:S)
1 | - ZADD key score1 member1 [score2 member2] 向有序集合添加一个或多个成员,或者更新已存在成员的分数 |
HyperLogLog
Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。
什么是基数?
比如数据集 {1, 3, 5, 7, 5, 7, 8}, 那么这个数据集的基数集为 {1, 3, 5 ,7, 8}, 基数(不重复元素的个数)为5。 基数估计就是在误差可接受的范围内,快速计算基数。
四种基数统计方案
比如:在线人数统计
- 使用有序集合:这种方案能够同时储存在线的用户和用户上线时间,能够执行非常多的聚合计算,但是所消耗的内存也是非常可观的。
- 使用集合:这种方案能储存在线的用户,也能够执行一定的聚合计算,相对有序集合,所消耗的内存要小些,但是随着用户量的增多,消耗内存空间也处于增加状态。
- 使用hyperloglog:这种方案无论统计多少在线用户, 消耗的内存都是12k,但是只能给出在线用户的统计信息,无法获取准确的在线用户名单。
- 使用bitmap:这种方案还是比较好的,在尽可能节省内存空间情况下,记录在线用户的情况,而且能做一定的聚合运算。
Redis的发布订阅
Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。Redis 客户端可以订阅任意数量的频道。
基本模型
下面两张图,第一张代表了订阅端对频道的订阅情况(即:3个客户端订阅了channel1这个频道的消息);第二张图则表示当发送端发送消息时,消息通过该频道会推送到所有已订阅该频道的客户端(注:这里的模式和kafka稍有差异,kafka是客户端主动去pull消息的,而redis的客户端接收消息是由channel发起的push操作,本质不一样)。
命令说明
1 | - PSUBSCRIBE pattern [pattern ...] 订阅一个或多个符合给定模式的频道。 |
实例演示
1 | # client订阅一个channel |
Redis的事务
事务特性
单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。
事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。redis的事务执行有以下特征:
- 批量操作在发送 EXEC 命令前被放入队列缓存。
- 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。
- 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。
命令说明
1 | - DISCARD 取消事务,放弃执行事务块内的所有命令。 |
操作实例
1 | # 如果在 set b bbb 处失败,set a 已成功不会回滚,set c 还会继续执行。 |
补充说明
From redis docs on transactions: It’s important to note that even when a command fails, all the other commands in the queue are processed – Redis will not stop the processing of commands.
Redis的安装
安装步骤
这个章节实际是验证OpenResty和Redis结合做反爬虫时发现没有
Redis因为没有多余的外部依赖,直接编译安装即可(但5.0以上新版本的貌似有些差异,暂不考虑),在这里我们用了4.0.2的发行版进行的编译安装,一般自测就直接使用redis-server启动了。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[root@localhost ~]# wget http://download.redis.io/releases/redis-4.0.2.tar.gz
......
[root@localhost ~]# tar -zxvf redis-4.0.2.tar.gz
......
[root@localhost ~]# cd redis-4.0.2
[root@localhost redis-4.0.2]# make
cd src && make all
make[1]: Entering directory `/root/redis-4.0.2/src'
......
make[1]: Leaving directory `/root/redis-4.0.2/src'
[root@localhost redis-4.0.2]# make install
cd src && make install
make[1]: Entering directory `/root/redis-4.0.2/src'
......
INSTALL install
make[1]: Leaving directory `/root/redis-4.0.2/src'
[root@localhost redis-4.0.2]# redis-server
5367:C 18 Dec 21:15:26.420 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
5367:C 18 Dec 21:15:26.420 # Redis version=4.0.2, bits=64, commit=00000000, modified=0, pid=5367, just started
5367:C 18 Dec 21:15:26.420 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
5367:M 18 Dec 21:15:26.421 * Increased maximum number of open files to 10032 (it was originally set to 1024).
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 4.0.2 (00000000/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in standalone mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 6379
| `-._ `._ / _.-' | PID: 5367
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | http://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
5367:M 18 Dec 21:15:26.421 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
5367:M 18 Dec 21:15:26.421 # Server initialized
5367:M 18 Dec 21:15:26.422 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. ...
5367:M 18 Dec 21:15:26.422 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. ...
5367:M 18 Dec 21:15:26.422 * Ready to accept connections
^C5367:signal-handler (1545186523) Received SIGINT scheduling shutdown...
5367:M 18 Dec 21:28:43.443 # User requested shutdown...
5367:M 18 Dec 21:28:43.443 * Saving the final RDB snapshot before exiting.
5367:M 18 Dec 21:28:43.445 * DB saved on disk
5367:M 18 Dec 21:28:43.445 # Redis is now ready to exit, bye bye...
[root@localhost redis-4.0.2]# ^C
[root@localhost redis-4.0.2]#
后台运行
若期望服务进程在后台运行,可通过redis.conf文件的daemonize配置项来解决,然后通过指定启动配置文件的方式来启动redis-server,这样就可以实现了:1
2
3
4
5
6
7
8[root@smart0002 redis-4.0.2]# redis-server /etc/redis.conf
5430:C 19 Dec 11:05:18.557 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
5430:C 19 Dec 11:05:18.558 # Redis version=4.0.2, bits=64, commit=00000000, modified=0, pid=5430, just started
5430:C 19 Dec 11:05:18.558 # Configuration loaded
[root@smart0002 redis-4.0.2]# ps -ef|grep redis
root 5431 1 0 11:05 ? 00:00:00 redis-server 127.0.0.1:6379
root 5446 29178 0 11:05 pts/6 00:00:00 grep redis
[root@smart0002 redis-4.0.2]#
简单验证
在上面安装部署完成后,可通过自带的redis-cli连接进入缓存库(有点类似于mysql的命令操作模式),进入缓存库后可通过一系列的命令达到自己想要的目的(以下仅是很简单的示范):1
2
3
4
5
6
7
8
9
10
11[root@localhost ~]# redis-cli -h localhost -p 6379
localhost:6379> dbsize
(integer) 4
localhost:6379> keys *
1) "timing_start_192.168.1.137"
2) "access_total_12/18/18"
3) "access_count_192.168.1.137"
4) "ban_time_192.168.1.137"
localhost:6379> get timing_start_192.168.1.137
"1545186401"
localhost:6379>