0%

Redis快速上手

Redis头图

Redis 是一个使用 C 语言编写的开源、支持网络、基于内存、可选持久性的键值对存储数据库。


Redis的特点

  • 读写速度快:Redis 将数据存储在内存中,每秒钟支持大约8万次写操作和11万次读操作
  • 数据类型丰富:Redis 提供了包括 String、List、Hash、Set、SortedSet五种类型
    • 数据类型丰富指的是 value 的类型,其 key 只有 String 类型
  • 数据切换方便:Redis 支持将数据复制到任意一台装有 Redis 数据库的服务器中
  • 原子性:Redis 所有的操作都是原子性的,从而保证数据的完整性

安装Redis

需求

  • 软件安装目录:/export/servers
  • 源码存放目录:/export/software
  • 日志文件目录:/export/logs
  • 数据存放目录:/export/data

创建目录

1
2
3
4
5
#创建目录
mkdir -p /export/servers
mkdir -p /export/software
mkdir -p /export/logs
mkdir -p /export/data

下载源码包

下载 Redis,解包后重命名。注意:这里的 redis-src 是用来编译安装的文件夹(源码)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#software 目录存放源码包
cd /export/software/

#下载 Redis 源码包
wget http://download.redis.io/releases/redis-4.0.2.tar.gz

#解压 Redis 源码包
tar -zxvf redis-4.0.2.tar.gz -C ../servers

#servers 目录安装软件
cd /export/servers/

#重命名
mv redis-4.0.2 redis-src

安装编译环境

下载下来的只是 Redis 的源码包,需要对其进行编译,故需要安装C语言编译环境。

1
2
#安装C语言编译环境
yum -y install gcc gcc-c++ libstdc++-devel tcl -y

编译与安装

1
2
3
4
5
6
7
cd /export/servers/redis-src/

#进行编译 MALLOC--动态内存分配
make MALLOC=libc

#安装 PREFIX--软件安装位置
make PREFIX=/export/servers/redis install

准备配置文件

在指定的位置创建 Redis 的配置文件。

1
2
3
4
5
6
#创建配置目录
mkdir -p /export/servers/redis/conf
cd /export/servers/redis/conf

#创建 Redis 配置文件
vi redis_6379.conf

配置文件的内容如下:

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
#单节点Redis
bind 192.168.153.100
protected-mode yes
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize yes
supervised no
pidfile /export/data/redis/6379/redis_6379.pid
loglevel notice
logfile "/export/data/redis/6379/log.log"
databases 16
always-show-logo yes
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /export/data/redis/6379/
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
slave-priority 100
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
slave-lazy-flush no
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble no
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes

Redis 集群:

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
#Redis集群
bind 192.168.153.100
protected-mode yes
port 7001
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize yes
+ cluster-enabled yes
+ cluster-config-file redis.conf
+ cluster-node-timeout 5000
supervised no
pidfile /export/data/redis/7001/redis.pid
loglevel notice
logfile "/export/data/redis/7001/log.log"
databases 16
always-show-logo yes
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /export/data/redis/7001/
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
slave-priority 100
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
slave-lazy-flush no
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble no
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes

说明:

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
#IP地址,改为自己的IP
bind 192.168.153.100
#是否允许远程访问
protected-mode yes
#端口号
port 6379
#tcp传输方式
tcp-backlog 511
#连接超时设置
timeout 0
#连接存活时长
tcp-keepalive 300
#守护进行方式运行(后台)
daemonize yes
#是否监督
supervised no
#守护进程pid文件位置
pidfile /export/data/redis/6379/redis_6379.pid
#日志级别
loglevel notice
#日志文件位置
logfile "/export/data/redis/6379/log.log"
#数据库个数
databases 16
#是否总显示logo
always-show-logo yes
#RDB持久化方式参数设置
save 900 1
save 300 10
save 60 10000
#当快照操作出错时是否停止写入磁盘
stop-writes-on-bgsave-error yes
#RDB文件是否压缩
rdbcompression yes
#RDB是否检查数量
rdbchecksum yes
#RDB的文件名
dbfilename dump.rdb
#文件存储位置
dir /export/data/redis/6379/
#主从节点数据处理方式(集群才考虑)
slave-serve-stale-data yes
#从节点只读
slave-read-only yes
#默认不是用diskless同步方式
repl-diskless-sync no
#同步延迟5秒
repl-diskless-sync-delay 5
#是否启用TCP_NODELAY 启用会是用少量宽带向slave传输,速度会比较慢
repl-disable-tcp-nodelay no
#从节点优先级设置,整数
slave-priority 100
#被动删除数据--最大内存
lazyfree-lazy-eviction no
#被动删除数据--TTL键,过期删除
lazyfree-lazy-expire no
#被动删除数据--如果存在目标键(例如rename),会先删除目标键
lazyfree-lazy-server-del no
#从节点进行全局数据同步,同步前清空数据
slave-lazy-flush no
#AOF持久化方式
appendonly yes
#AOF文件名称
appendfilename "appendonly.aof"
#持久化方式-每秒
appendfsync everysec
#当主进程写操作时,是否会阻止其他fsync调用
no-appendfsync-on-rewrite no
#aof文件触发自动rewrite的百分比
auto-aof-rewrite-percentage 100
#aof文件大小最小值
auto-aof-rewrite-min-size 64mb
#是否加载不完整的aof文件进行启动
aof-load-truncated yes
#AOF和RDB混合开关
aof-use-rdb-preamble no
#lua脚本运行的最大时间
lua-time-limit 5000
#redis执行时间(微秒级),为了不遗漏数据
slowlog-log-slower-than 10000
#slowlog数据的最大长度
slowlog-max-len 128
#延迟监控,用于记录等于或超过了指定时间的操作
latency-monitor-threshold 0
#事件通知,默认不启用
notify-keyspace-events ""
#hash是否采用高效结构的条数和大小阈值
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
#list高效方式的阈值
list-max-ziplist-size -2
list-compress-depth 0
#set和sortedSet集合高效方式的阈值
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
#设置HyeperLogLog的字节数限制,这个值通常在0~15000之间
hll-sparse-max-bytes 3000
#redis每秒中抽出10毫秒对主字典进行重新散列化处理,有助于释放内存
activerehashing yes
#normal\slave\pubsub三种客户端如果从主服务获取数据时过慢,超过限制,将可能会使client失连
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
#设置CPU参数,执行redis内部程序处理后台任务
hz 10
#当一个子进程要改写AOF文件,那文件会在每产生32MB数据时进行同步,避免出现延迟
aof-rewrite-incremental-fsync yes

启动Redis

1
2
3
4
5
6
7
8
#创建数据目录
mkdir -p /export/data/redis/6379/

#进入bin目录
cd /export/servers/redis/bin/

#以配置启动 Redis
./redis-server ../conf/redis_6379.conf

查看是否正常启动 Redis 服务

1
2
3
4
#查看是否正确启动
$ ps -ef|grep redis
root 3485 1 0 19:24 ? 00:00:00 ./redis-server 192.168.153.101:6379
root 3491 2010 0 19:24 pts/0 00:00:00 grep redis

Redis 分为服务端和客户端,刚刚我们已经启动了 Redis 的服务端,接下来就可以使用客户端连接 Redis 了

使用客户端连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cd /export/servers/redis/

# 连接Redis,输入ping命令进行检测,返回 PONG 表示成功
# bin/redis-cli -h 192.168.153.100
192.168.153.100:6379> ping
PONG

# 连接Redis集群
# bin/redis-cli -c -h node01 -p 7001
node01:7001> set IpBlackListChangeFlag true
-> Redirected to slot [15902] located at 192.168.153.100:7003
OK

# 退出客户端
192.168.153.100:7003> quit

Jedis

Jedis 是一款用于操作 Redis 数据库的Java 客户端工具,提供了一套易于使用的 API。Jedis 其最大的特点就是其 API 和 Redis 的命令相同,大大降低了学习成本,其本身也被 Redis 官方推荐。

开源地址:xetorthio / jedis

快速入门

  1. 新建Maven项目,导入jedis和junit依赖。
1
2
3
4
5
6
7
8
9
10
11
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
  1. 创建测试类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Test
public void jedisTest() {
//1. 创建jedis对象
Jedis jedis = new Jedis("192.168.153.100", 6379);

//2. 测试是否连通
String pong = jedis.ping();

//返回PONG 表示已经连通
System.out.println(pong);

//3. 释放资源
jedis.close();
}

常用API

String类型

使用 Redis 操作 String 类型数据。

  • 特点:存储所有的字符和字符串
  • 应用场景:做缓存使用
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
public class StringTest {
Jedis jedis = null;

//1. 创建 jedis 对象
@Before()
public void before() {
jedis = new Jedis("192.168.153.100", 6379);
}

//3. 释放资源
@After
public void after() {
jedis.close();
}

//2. 操作 jedis

//存值
@Test
public void set() {
jedis.set("age", "23");
}

//取值
@Test
public void get() {
String age = jedis.get("age");
System.out.println(age); //23
}

//删除值
@Test
public void del() {
jedis.del("age");
String age = jedis.get("age");
System.out.println(age); //null
}

//数值增减
@Test
public void incrDecr() {
//自增
jedis.incr("age");
System.out.println(jedis.get("age")); //24
//自减
jedis.decr("age");
System.out.println(jedis.get("age")); //23
//增加指定量
jedis.incrBy("age", 5);
System.out.println(jedis.get("age")); //28
//减少指定量
jedis.decrBy("age", 5);
System.out.println(jedis.get("age")); //23
}

//追加
@Test
public void append() {
//如果该 key 不存在,创建该 key-value
jedis.append("name", "蔡");
System.out.println(jedis.get("name")); //蔡
//如果该 key 存在,在原有 value 后追加该 value
jedis.append("name", "徐坤");
System.out.println(jedis.get("name")); //蔡徐坤
}

//有效时长
@Test
public void expire() throws InterruptedException {
//为新建的 key 设置有效时长
jedis.setex("hobby", 5, "篮球");

//为已有的 key 设置有效时长
Long flag = jedis.expire("name", 5);
//返回 1 表示设置成功,返回 0 表示该 key 不存在
System.out.println(flag); //1

//判断该 key 是否存在
while (jedis.exists("name")) {
//返回剩余有效时长,-1 表示永久有效,-2 表示不存在
System.out.println(jedis.ttl("name")); //间隔一秒依次打印 5 4 3 2 1 0
Thread.sleep(1000);
}
}
}

List类型

使用 Redis 操作 list 类型数据。

  • 特点: 相当于 java 中linkList,是一个链表的结构
  • 应用场景: 做任务队列,在 java 客户端中提供了线程安全获取集合数据的方式
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
/**
* jedis 操作 redis --> list
* list 可以将其看做是 java 的队列类似
* list 数据类型的应用场景:任务队列
*/
public class ListTest {
private Jedis jedis = null;

//1. 创建 jedis 对象
@Before()
public void before() {
jedis = new Jedis("192.168.153.100", 6379);
}

//3. 释放资源
@After
public void after() {
jedis.close();
}

//2. 操作 jedis

//左侧添加
@Test
public void lpush() {
jedis.lpush("list1", "a", "b", "c", "d");
}

//右侧弹出
@Test
public void rpop() {
String list1 = jedis.rpop("list1");
System.out.println(list1); //a
}

//右侧添加
@Test
public void rpush() {
jedis.rpush("list2", "a", "b", "c", "d");
}

//左侧弹出
@Test
public void lpop() {
String list2 = jedis.lpop("list2");
System.out.println(list2); //a
}

//查看 list 某个范围的数据
@Test
public void lrange() {
List<String> list1 = jedis.lrange("list1", 0, -1);
System.out.println(list1); //[d, c, b]
}

//获取元素个数
@Test
public void llen() {
Long list1 = jedis.llen("list1");
System.out.println(list1); //3
}

//插入
@Test
public void linsert() {
//在 b 元素前插入 0
jedis.linsert("list1", BinaryClient.LIST_POSITION.BEFORE, "b", "0");
//在 c 元素后插入 1
jedis.linsert("list1", BinaryClient.LIST_POSITION.AFTER, "c", "1");
System.out.println(jedis.lrange("list1", 0, -1)); //[d, c, 1, 0, b]
}

//将 list1 中的尾部元素弹出,插入为 list2 的头部元素,list1 和 list2 可以是同一个 list
@Test
public void rpoplpush() {
System.out.println("before");
System.out.println(jedis.lrange("list1", 0, -1)); //[d, c, 1, 0, b]
System.out.println(jedis.lrange("list2", 0, -1)); //[b, c, d]

jedis.rpoplpush("list1", "list2");

System.out.println("after");
System.out.println(jedis.lrange("list1", 0, -1)); //[d, c, 1, 0]
System.out.println(jedis.lrange("list2", 0, -1)); //[b, b, c, d]
}

//删除元素
@Test
public void lrem() {
//重置 list3 数据
jedis.del("list3");
jedis.lpush("list3", "a", "b", "c", "c", "b", "a");
System.out.println(jedis.lrange("list3", 0, -1)); //[a, b, c, c, b, a]

//从头到尾遍历删除 1 个 list3 中值为 a 的元素
jedis.lrem("list3", 1, "a");
System.out.println(jedis.lrange("list3", 0, -1)); //[b, c, c, b, a]

//从尾到头遍历删除 2 个 list3 中值为 b 的元素
jedis.lrem("list3", -2, "b");
System.out.println(jedis.lrange("list3", 0, -1)); //[c, c, a]

//删除 list3 中值为 c 的全部元素
jedis.lrem("list3", 0, "c");
System.out.println(jedis.lrange("list3", 0, -1)); //[a]
}
}

//TODO

Hash类型

哈希 hash

  • 特点:相当于 java 中的 HashMap 集合
  • 应用场景:可以存储 javaBean 对象,此种使用场景不多,可被String替代
1

Set类型

set 集合

  • 特点: 唯一,无序
  • 应用场景:集合运算,例如去重复的操作
1

SortedSet类型

有序set集合: sorted set

  • 特点:唯一,有序
  • 应用场景: 一般用来做排行榜
1

//TODO Redis集群

  • 本文作者: SANNAHA
  • 本文链接: https://sannaha.moe/Redis/
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!