一. Redis的介绍
1.1 引言
- 由于用户量增大, 请求数量也增大, 数据库压力过大
- 多台服务器之间, 数据不同步
- 多台服务器之间的锁, 已经不存在互斥性了
1.2 NoSql
Redis就是一款NoSql
NoSql -> 非关系型数据库 -> Not Only Sql
- Key - Value : Redis…
- 文档型 : ElasticSearch, Solr, Mongodb…
- 面向列 : Hbase, Cassandra…
- 图像化 : Neo4j…
除了关系型数据库都是非关系型数据库
NoSql只是一个概念, 泛指非关系型数据库, 目的是为了和关系型数据库做一个区分
1.3 Redis介绍
有一位意大利人, Salvatore, 在开发一款LLOOGG的统计页面时, 因为MySQL的性能不好, 自己研发了一款非关系型数据库, 命名为Redis.
Redis ( Remote Dictionary Server ) 即远程字典服务
- Redis由c语言编写, 是基于Key - Value的NoSql
- Redis基于内存存储数据, 还提供了多种持久化机制, 性能可以达到110000次/s读取数据以及81000次/s写入数据
- Redis提供了主从, 哨兵以及集群的搭建方式, 可以更加方便的进行横向扩展和垂直扩展
二. Redis的安装
2.1 安装Redis
docker-compose.yml
version: '3.1'
services:
redis:
image: daocloud.io/library/redis:5.0.7
restart: always
container_name: redis
environment:
- TZ=Asia/Shanghai
ports:
- 6379:6379
使用docker命令启动容器: docker-compose up -d
2.2 使用redis-cli连接Redis
使用docker命令进入容器内部: docker exec -it 容器id bash
在容器内部使用Redis客户端连接命令: redis-cli
2.3 使用图形化界面连接Redis
使用Redis可视化软件Redis desktop manager连接
三. Redis的常用命令(Redis命令参考文档)
3.1 Redis存储数据的结构
常用的5种数据结构
- key - value : 一个key对应一个值
- key - hash : 一个key对应一个map
- key - list : 一个key对应一个列表
- key - set : 一个key对应一个集合
- key - zset : 一个key对应一个有序的集合
另外的3中数据结构
HyperLogLog : 计算近似值
GEO : 地理位置
BIT : 一般存储的也是一个字符串, 存储的是一个byte[]
常用的5种数据结构图:
常用的5种数据结构使用场景:
key - value : 最常用的, 一般用于存储一个值
key - hash : 存储一个对象数据
key - list : 实现队列和栈结构
key - set : 交集, 差集和并集的操作
key - zset : 排行榜, 积分存储等操作
3.2 string常用命令
#1. 添加值(如果key存在, 为更新操作)
set key value
#2. 取值
get key value
#3. 删除(可以同时删除多个key)
del key1 [key2 key3 ...]
#4. 批量操作
mset key1 value [key2 value key3 value ...]
mget key1 key2 key3 ...
#5. 自增命令(自增1)
incr key
#6. 自减命令(自减1)
decr key
#7. 自增或自减指定数量
incrby key increment
decrby key increment
#8. 设置值的同时, 指定生存时间(每次向Redis中添加数据时, 尽量都设置上)
setex key second value
#9. 设置值, 如果当前key不存在的话(如果这个key存在, 那么什么都不做, 如果key不存在, 和set命令一样)
setnx key value
#10. 在key对应的value后, 追加内容
append key value
#11. 查看value字符串的长度
strlen key
3.3 hash常用命令
#1. 添加数据(如果field存在, 则为更新操作)
hset key field value
#2. 获取数据
hget key field
#3. 删除数据
hdel key field1 [field2 field3 ...]
#4. 批量操作
hmset key field1 value1 [field2 value2 ...]
hmget key field1 [field2 ...]
#5. 自增自减(根据increment正负)
hincrby key field increment
#6. 获取key中全部的field和value
hgetall key
#7. 获取key中所有的field
hkeys key
#8. 获取key中所有的value
hvals key
#9. 判断key中是否含有某个field字段
hexists key field
#10. 获取key中field数量
hlen key
3.4 list常用命令
#1. 添加数据(从左侧添加数据, 从右侧添加数据)
lpush key value1 [value2 value3 ...]
rpush key value1 [value2 value3 ...]
#2. 追加数据(如果key不存在或者key的数据类型不是list, 则什么也不做)
lpushx key value
rpushx key value
#3. 修改数据(将某个索引位置的数据更新)
lset key index value
#4. 弹栈方式获取数据(从左侧弹出, 从右侧弹出, 弹出后删除)
lpop key
rpop key
#5. 获取指定范围内的数据(start从0开始, stop输入-1代表最后一个, -2代表倒数第二个)
lrange key start stop
#6. 获取指定索引位置的数据
lindex key index
#7. 获取整个列表的长度
llen key
#8. 删除列表中某个value(删除当前列表中count个value值, count > 0 从左侧删除, count < 0 从右侧删除, count == 0 删除列表中全部数据)
lrem key count value
#9. 保留列表中的数据
ltrim key start stop
3.5 set常用命令
#1. 添加数据
sadd key member1 [member2 member3 ...]
#2. 获取数据
smembers key
#3. 随机获取数据(获取的同时, 移除数据, count默认值为1, 代表弹出数据的数量)
spop key [count]
#4. 删除数据
srem key member1 [member2 ...]
#5. 判断集合中是否包含某个值
sismember key member
#6. 交集
sinter set1 set2
#7. 并集
sunion set1 set2
#8. 差集
sdiff set1 set2
3.6 zset常用命令
#1. 添加数据
zadd key score member1 [score member2 score member3 ... ]
#2. 修改分数(如果member存在与key中, 正常增加分数, 如果不存在, 这个命令就相当于zadd)
zincrby key increment member
#3. 查看指定的member的分数
zscore key member
#4. 删除zset中的成员
zrem key member1 [member2 member3 ...]
#5. 获取zset中数据的数量
zcard key
#6. 根据score的范围查询member的数量
zcount key min max
#7. 根据分数从小到大排序, 获取指定范围内的数据(withscores 如果添加这个参数, 那么会返回member对应的分数)
zrange key start stop [withscores]
#8. 根据分数从大到小排序, 获取指定范围内的数据(withscores 如果添加这个参数, 那么会返回member对应的分数)
zrevrange key start stop [withscores]
#9. 根据分数的范围从小到大获取member(withscores 代表同时返回score, 添加limit, 就跟mysql中一样. 支持 '(分数' 相当于 '<' 但是不等于, 最大值和最小值分别用 +inf 和 -inf 来表示)
zrangebyscore key min max [limit offset count]
#10. 根据分数的范围从大到小获取member(withscores 代表同时返回score, 添加limit, 就跟mysql中一样. 支持 '(分数' 相当于 '<' 但是不等于, 最大值和最小值分别用 +inf 和 -inf 来表示)
zrevrangebyscore key max min [limit offset count]
3.7 key常用命令
#1. 查找所有符合给定模式 pattern 的 key
keys pattern
KEYS * 匹配数据库中所有 key 。
KEYS h?llo 匹配 hello , hallo 和 hxllo 等。
KEYS h*llo 匹配 hllo 和 heeeeello 等。
KEYS h[ae]llo 匹配 hello 和 hallo ,但不匹配 hillo 。
#2. 检查给定 key 是否存在( 1 - 存在, 0 - 不存在 )
exists key
#3. 查看key所存储的值的类型
type key
none
(key不存在)string
(字符串)list
(列表)set
(集合)zset
(有序集)hash
(哈希表)stream
(流)
#4. 删除一个或者多个key
del key1 [key2 key3 ...]
3.8 库的常用命令
#1. 切换到指定的数据库,数据库索引号 index 用数字值指定,以 0 作为起始索引值
select index
#2. 返回当前数据库的 key 的数量
dbsize
#3. 清空当前数据库中的所有数据
flushdb
#4. 清空Redis服务器中所有数据
flushall
3.9 过期时间命令
#1. 为指定的key设置过期时间, 还能活多久(秒, 毫秒)
expire key seconds
pexpire key milliseconds
#2. 设置key到 某个时间点 过期, 能活到哪个时间点(秒单位, 毫秒单位)
expireat key timestamp
pexpireat key milliseconds-timestamp
#3. 移除指定key的过期时间, 使其变为永不过期
persist key
#4. 查询某个key的过期时间(秒, 毫秒)
ttl key
pttl key
四. Java连接Redis
Jedis连接Redis, lettuce连接Redis
4.1 Jedis连接Redis
创建maven项目
引入依赖
<dependencies>
<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>
</dependencies>
测试
public class Demo1 {
@Test
public void set() {
Jedis jedis = new Jedis("192.168.153.129", 6379);
jedis.set("name", "张三");
jedis.close();
}
@Test
public void get() {
Jedis jedis = new Jedis("192.168.153.129", 6379);
String name = jedis.get("name");
System.out.println(name);
jedis.close();
}
}
4.2 Jedis如何存储一个对象到Redis, 以byte[]的方式
引入依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
新建User类
public class User implements Serializable {
private static final long serialVersionUID = -9066097709281121769L;
private String name;
private Integer age;
public User() {
}
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
测试
@Test
public void setByteArray() {
// 1. 建立连接
Jedis jedis = new Jedis("192.168.153.129", 6379);
// 2.1 准备key - value(User)
String key = "user";
User user = new User("王五", 25);
// 2.2 将key和value转化为byte[]
byte[] keyByte = SerializationUtils.serialize(key);
byte[] userByte = SerializationUtils.serialize(user);
// 2.3 将byte[]存储到Redis中
jedis.set(keyByte, userByte);
// 3. 关闭连接
jedis.close();
}
@Test
public void getByteArray() {
// 1. 建立连接
Jedis jedis = new Jedis("192.168.153.129", 6379);
// 2. 执行操作
byte[] key = SerializationUtils.serialize("user");
byte[] value = jedis.get(key);
System.out.println(SerializationUtils.deserialize(value));
// 3. 关闭连接
jedis.close();
}
4.3 Jedis如何存储一个对象到Redis, 以String的方式
引入依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
测试
@Test
public void setString() {
// 1. 建立连接
Jedis jedis = new Jedis("192.168.153.129", 6379);
// 2.1 准备key - value
String key = "userString";
User user = new User("赵六", 88);
// 2.2 将对象转换为json字符串
String value = JSON.toJSONString(user);
// 2.3 执行存储操作
jedis.set(key, value);
// 3. 关闭连接
jedis.close();
}
@Test
public void getString() {
// 1. 建立连接
Jedis jedis = new Jedis("192.168.153.129", 6379);
// 2.1 准备key
String key = "userString";
// 2.2 获取value
String value = jedis.get(key);
// 2.3 value转化为对象并输出
User user = JSON.parseObject(value, User.class);
System.out.println(user);
// 3. 关闭连接
jedis.close();
}
4.4 Jedis连接池操作
@Test
public void pool() {
// 1. 创建连接池配置
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
// 连接池中最大活跃数
config.setMaxTotal(100);
// 最大空闲数
config.setMaxIdle(10);
// 最小空闲数
config.setMinIdle(5);
// 当线程池空了以后, 多久没有获取到Jedis对象, 就超时
config.setMaxWaitMillis(3000);
// 2. 创建连接池
JedisPool jedisPool = new JedisPool(config, "192.168.153.129", 6379);
// 3. 获取Redis对象
Jedis jedis = jedisPool.getResource();
// 4. 执行操作
String userString = jedis.get("userString");
System.out.println(userString);
// 5. 释放资源
jedis.close();
}
4.5 Redis的管道操作
@Test
public void pipelineTest1() {
long startTime = System.currentTimeMillis();
// 1. 创建连接池对象
JedisPool jedisPool = new JedisPool("192.168.153.129", 6379);
// 2. 获取Jedis对象
Jedis jedis = jedisPool.getResource();
// 3. 执行操作
for (int i = 0; i < 100000; i++) {
jedis.incr("yy");
}
// 4. 释放资源
jedis.close();
long endTime = System.currentTimeMillis();
System.out.println(endTime - startTime);
}
@Test
public void pipelineTest2() {
long startTime = System.currentTimeMillis();
// 1. 创建连接池对象
JedisPool jedisPool = new JedisPool("192.168.153.129", 6379);
// 2. 获取Jedis对象
Jedis jedis = jedisPool.getResource();
// 3. 将命令放进管道
Pipeline pipelined = jedis.pipelined();
for (int i = 0; i < 100000; i++) {
pipelined.incr("xx");
}
// 4.执行命令
pipelined.sync();
// 5. 释放资源
jedis.close();
long endTime = System.currentTimeMillis();
System.out.println(endTime - startTime);
}
五. Redis其他配置和集群
修改yml文件, 以方便修改Redis配置文件
version: '3.1'
services:
redis:
image: daocloud.io/library/redis:5.0.7
restart: always
container_name: redis
environment:
- TZ=Asia/Shanghai
ports:
- 6379:6379
volumes:
- ./conf/redis.conf:/usr/local/redis/redis.conf
command: ["redis-server","/usr/local/redis/redis.conf"]
5.1 Redis的Auth配置
方式一: 通过修改Redis配置文件, 实现Redis的密码校验
# redis.conf
requirepass 密码
三种客户端的连接方式
redis-cli : 在输入正常命令之前, 先输入auth 密码 即可
图形化界面 : 在连接redis的信息中添加上验证的密码
Jedis客户端:
第一种 : jedis.auth(password)
第二种 :
public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, int timeout, String password) {
}
方式二 : 在不修改redis.conf文件的前提下, 在第一次链接redis时, 输入命令 : config set requirepass 密码, 后续向再次操作redis时,
需要先auth做一下校验
5.2 Redis的事务
Redis的事务 : 一次事务操作, 该成功的成功, 该失败的失败
先开启事务, 执行一系列的命令, 但是密码不会立即执行, 而是把这些命令放到一个队列中, 如果执行事务, 那么这个队列中的命令全部执行,
如果取消了事务, 一个队列中的命令全部作废
- 开启事务 : multi
- 输入要执行的命令 : 被放到一个队列中
- 执行事务 : exec
- 取消事务 : discard
Redis的事务想要发挥功能, 需要配置watch监听机制
在开启事务之前, 先通过watch命令去监听一个或多个key, 在开启事务之后, 如果有其他客户端修改了我监听的key, 事务会自动取消
如果执行了事务, 或者取消了事务, watch监听自动消除, 所以一般不需要执行unwatch
5.3 Redis的持久化机制-RDB
RDB是Redis的默认持久化机制
RDB持久化文件, 速度比较快, 而且存储的是二进制文件, 传输起来很方便
RDB持久化的时机:
save 900 1 : 在900秒内, 有1个key改变了, 就执行RDB持久化
save 300 10 : 在300秒内, 有10个key改变了, 就执行RDB持久化
save 60 10000 : 在60秒内, 有10000个key改变了, 就执行RDB持久化
RDB无法保证数据的绝对安全
5.4 Redis的持久化机制-AOF
AOF持久化机制默认是关闭的, Redis官方推荐同事开启RDB和AOF持久化, 更安全, 避免数据丢失
appendonly no ==> appendonly yes
appendfilename “appendonly.aof” : AOF持久化文件名称
AOF持久化的速度, 相对RDB较慢, 存储的是一个文本文件, 到了后期文件会比较大, 传输困难
AOF持久化的时机:
appendfsync always : 每执行一个写操作, 立即持久化到AOF文件中, 性能比较低
appendfsync everysec : 每秒执行一次持久化
appendfsync no : 会根据操作系统的不同, 环境的不同, 在一定时间内执行一次持久化
AOF相对RDB更安全, 推荐同时开启RDB和AOF
同时开启RDB和AOF的注意事项 :
如果同时开启RDB和AOF持久化, 那么在Redis宕机之后, 需要加载一个持久化文件, 优先选择AOF文件
如果先开启了RDB, 执行了持久化以后, 再开启AOF, 那么RDB文件中的内容会被AOF覆盖掉
5.5 Redis的主从架构
单机版Redis存在读写瓶颈问题
主从架构:
- 主从复制(步骤)
- 单点故障
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zF28MiXa-1641458309854)(C:\Users\123\AppData\Roaming\Typora\typora-user-images\image-20210616102833987.png)]
version: "3.1"
services:
redis1:
image: daocloud.io/library/redis:5.0.7
restart: always
container_name: redis1
environment:
- TZ=Asia/Shanghai
ports:
- 7001:6379
volumes:
- ./conf/redis1.conf:/usr/local/redis/redis.conf
command: ["redis-server","/usr/local/redis/redis.conf"]
redis2:
image: daocloud.io/library/redis:5.0.7
restart: always
container_name: redis2
environment:
- TZ=Asia/Shanghai
ports:
- 7002:6379
volumes:
- ./conf/redis2.conf:/usr/local/redis/redis.conf
links:
- redis1:master
command: ["redis-server","/usr/local/redis/redis.conf"]
redis3:
image: daocloud.io/library/redis:5.0.7
restart: always
container_name: redis3
environment:
- TZ=Asia/Shanghai
ports:
- 7003:6379
volumes:
- ./conf/redis3.conf:/usr/local/redis/redis.conf
links:
- redis1:master
command: ["redis-server","/usr/local/redis/redis.conf"]
# redis2和redis3从节点配置
replicaof master 6379
5.6 Redis的哨兵
哨兵模式能够解决Redis主从架构中的单点故障问题
- 哨兵之间相互通信
- master节点宕机后, 哨兵能够将一个从节点变为主节点, 解决单点故障
为了在容器内容使用哨兵的配置, 需要修改docker-compose.yml
version: "3.1"
services:
redis1:
image: daocloud.io/library/redis:5.0.7
restart: always
container_name: redis1
environment:
- TZ=Asia/Shanghai
ports:
- 7001:6379
volumes:
- ./conf/redis1.conf:/usr/local/redis/redis.conf
- ./conf/sentinel1.conf:/data/sentinel.conf
command: ["redis-server","/usr/local/redis/redis.conf"]
redis2:
image: daocloud.io/library/redis:5.0.7
restart: always
container_name: redis2
environment:
- TZ=Asia/Shanghai
ports:
- 7002:6379
volumes:
- ./conf/redis2.conf:/usr/local/redis/redis.conf
- ./conf/sentinel2.conf:/data/sentinel.conf
links:
- redis1:master
command: ["redis-server","/usr/local/redis/redis.conf"]
redis3:
image: daocloud.io/library/redis:5.0.7
restart: always
container_name: redis3
environment:
- TZ=Asia/Shanghai
ports:
- 7003:6379
volumes:
- ./conf/redis3.conf:/usr/local/redis/redis.conf
- ./conf/sentinel3.conf:/data/sentinel.conf
links:
- redis1:master
command: ["redis-server","/usr/local/redis/redis.conf"]
准备哨兵的配置文件, 并且在容器中启动哨兵即可
# 哨兵需要后台启动
daemonize yes
# 指定master节点的IP和端口(主节点配置行, 需要把下面的从节点配置行注释掉)
sentinel monitor master localhost 6379 2
# 指定master节点的IP和端口(从节点配置行, 需要把上面的主节点配置行注释掉)
sentinel monitor master master 6379 2
# 哨兵每隔多久监听一次Redis架构
sentinel down-after-milliseconds master 10000
启动哨兵命令:
redis-sentinel sentinel.conf
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CcSgF9ai-1641458309855)(C:\Users\123\AppData\Roaming\Typora\typora-user-images\image-20210618143400905.png)]
5.7 Redis的集群
Redis集群在保证主从加哨兵的基本功能之外, 还能够提升Redis存储数据的能力
Redis集群架构图
# docker-compose.yml
version: "3.1"
services:
redis1:
image: daocloud.io/library/redis:5.0.7
restart: always
container_name: redis1
environment:
- TZ=Asia/Shanghai
ports:
- 7001:7001
- 17001:17001
volumes:
- ./conf/redis1.conf:/usr/local/redis/redis.conf
command: ["redis-server","/usr/local/redis/redis.conf"]
redis2:
image: daocloud.io/library/redis:5.0.7
restart: always
container_name: redis2
environment:
- TZ=Asia/Shanghai
ports:
- 7002:7002
- 17002:17002
volumes:
- ./conf/redis2.conf:/usr/local/redis/redis.conf
command: ["redis-server","/usr/local/redis/redis.conf"]
redis3:
image: daocloud.io/library/redis:5.0.7
restart: always
container_name: redis3
environment:
- TZ=Asia/Shanghai
ports:
- 7003:7003
- 17003:17003
volumes:
- ./conf/redis3.conf:/usr/local/redis/redis.conf
command: ["redis-server","/usr/local/redis/redis.conf"]
redis4:
image: daocloud.io/library/redis:5.0.7
restart: always
container_name: redis4
environment:
- TZ=Asia/Shanghai
ports:
- 7004:7004
- 17004:17004
volumes:
- ./conf/redis4.conf:/usr/local/redis/redis.conf
command: ["redis-server","/usr/local/redis/redis.conf"]
redis5:
image: daocloud.io/library/redis:5.0.7
restart: always
container_name: redis5
environment:
- TZ=Asia/Shanghai
ports:
- 7005:7005
- 17005:17005
volumes:
- ./conf/redis5.conf:/usr/local/redis/redis.conf
command: ["redis-server","/usr/local/redis/redis.conf"]
redis6:
image: daocloud.io/library/redis:5.0.7
restart: always
container_name: redis6
environment:
- TZ=Asia/Shanghai
ports:
- 7006:7006
- 17006:17006
volumes:
- ./conf/redis6.conf:/usr/local/redis/redis.conf
command: ["redis-server","/usr/local/redis/redis.conf"]
# redis.conf
# 指定redis的端口号
port 7001
# 开启Redis集群
cluster-enabled yes
# 集群信息的文件
cluster-config-file nodes-7001.conf
# 集群对外的IP地址
cluster-announce-ip 192.168.153.129
# 集群对外的port
cluster-announce-port 7001
# 集群的总线端口
cluster-announce-bus-port 17001
启动了6个redis的节点
随便跳转到一个容器内部, 使用redis-cli管理集群
# 创建集群
redis-cli --cluster create 192.168.153.129:7001 192.168.153.129:7002 192.168.153.129:7003 192.168.153.129:7004 192.168.153.129:7005 192.168.153.129:7006 --cluster-replicas 1
# 注意: 如果出现Could not connect to Redis No route to host问题, 基本上都是防火墙的问题, 这时有两种解决办法
# 第一种: 关闭防火墙即可(不推荐): systemctl stop firewalld.service
# 第二种: 开放所需要的的端口
# 显示服务的状态
$ systemctl status firewalld.service
# 启动防火墙
$ systemctl start firewalld.service
# 开放7001...7006和17001...17006端口(如果不把总线端口开放, 会出现Waiting for the cluster to join 一直等待的问题)
firewall-cmd --add-port=7001/tcp --permanent
firewall-cmd --add-port=7002/tcp --permanent
firewall-cmd --add-port=7003/tcp --permanent
firewall-cmd --add-port=7004/tcp --permanent
firewall-cmd --add-port=7005/tcp --permanent
firewall-cmd --add-port=7006/tcp --permanent
firewall-cmd --add-port=17001/tcp --permanent
firewall-cmd --add-port=17002/tcp --permanent
firewall-cmd --add-port=17003/tcp --permanent
firewall-cmd --add-port=17004/tcp --permanent
firewall-cmd --add-port=17005/tcp --permanent
firewall-cmd --add-port=17006/tcp --permanent
firewall-cmd --reload
参数解释
1、firwall-cmd:是Linux提供的操作firewall的一个工具;
2、–permanent:表示设置为持久;
3、–add-port:标识添加的端口;
# 查看开放的端口
$ firewall-cmd --list-ports
# 查询7001端口是否开放
$ firewall-cmd --query-port=7001/tcp
# 移除7001端口
firewall-cmd --permanent --remove-port=7001/tcp
集群的连接
# 使用远程连接命令
redis-cli -h 192.168.153.129 -p 7001 -c
# 注意, 如果不加 -c 在执行命令时, 无法进行节点间的自动切换
5.8 java连接Redis集群
@Test
public void test() {
Set<HostAndPort> nodes = new HashSet<>();
nodes.add(new HostAndPort("192.168.153.129", 7001));
nodes.add(new HostAndPort("192.168.153.129", 7002));
nodes.add(new HostAndPort("192.168.153.129", 7003));
nodes.add(new HostAndPort("192.168.153.129", 7004));
nodes.add(new HostAndPort("192.168.153.129", 7005));
nodes.add(new HostAndPort("192.168.153.129", 7006));
JedisCluster jedisCluster = new JedisCluster(nodes);
String a = jedisCluster.get("c");
System.out.println(a);
}
六. Redis常见问题
6.1 Redis的删除策略
# 如果key的生存时间到了, Redis会立即删除掉它吗?
不会立即删除
1. 定期删除:
Redis每隔一段时间就会去查看设置了过期时间的key, 会在100ms的间隔默认查看3个key
2. 惰性删除:
如果当你去查询一个key时, Redis会先查看当前key的过期时间, 如果已经过期, 就执行删除当前key, 并且给用户返回一个空值
6.2 Redis的内存淘汰机制
Redis的删除策略导致内存会被填满, 需要设置一个有效的内存淘汰机制