一、背景
我们在开发互联网项目时,常常需要需要用到分布式缓存,目前最流行的分布式缓存就是Redis了,没有之一,接下来,开始我们的Redis实战之旅吧
二、安装单机Redis
1 版本选择
打开Redis官网,找一个版本下载,目前最新的版本号是7.2,一般我们都不用太新的,太新的有时候会出现兼容性问题,我们选择6.2版本(选择版本也可以通过看看SpringBoot默认引入的客户端版本号,然后根据客户端的版本号,看看其兼容的),因为Redis官网提供都是源码版本,所以只能下载源码然后自己编译,下载地址:https://github.com/redis/redis/releases/tag/6.2.13
2 编译安装
我这边用的是Centos7
1 安装C语言编译工具
yum install -y gcc tcl
2 将下载好的Redis源码上传到/usr/local/src,然后解压,如下:
3 进入到redis-6.2.13目录下执行
make && make install
4 默认安装目录为 /usr/local/bin
3 启动
任意目录执行下面命令即可启动Redis服务
redis-server
4 修改配置文件并后台启动
先备份配置文件
cp redis.conf redis.conf.bak
修改配置文件
# 修改下面配置
# 监听的地址
bind 0.0.0.0
# 后台启动
daemonize yes
# 最大内存
maxmemory 512mb
# 工作目录(日志,持久化文件等存放的地方)
dir /usr/local/redis/
# 日志目录,默认为空,不生成日志
logfile "redis.log"
# 连接密码
requirepass 123456
创建刚刚配置的工作目录 cd /usr/local/ & mkdir redis &启动服务
cd /usr/local
mkdir redis
redis-server src/redis-6.2.13/redis.conf
启动完成,查看一下进程ps -ef|grep redis
三、哨兵模式安装
前提看了上面的单机配置,会安装单机版,新配置在原来的单机配置的基础上修改的
我这边打算使用一台主机,通过不同的端口启动3台Redis实例和3台哨兵是咧,
采用一主二从三哨兵模式
1 端口规划
服务 | 端口 |
Redis | 6379 |
Redis | 6479 |
Redis | 6579 |
Sentinel | 26379 |
Sentinel | 26479 |
Sentinel | 26579 |
2 Redis主从配置
拷贝3个配置文件到/usr/local/etc 目录,分别命名为redis-6379.conf,redis-6479.conf,redis-6579.conf,6379端口为master,另外2个为从节点
# 端口号,需要在相应的配置文件修改端口
port 6379
# 工作目录,需要在相应的配置文件修改端口
dir /usr/local/redis/6379
# 主从节点都需要配置,后面可能会有主从切换的场景
masterauth 123456
# PID文件位置,需要在相应的配置文件修改端口
pidfile /usr/local/redis/6379/redis.pid
# 从节点单独需要配置 (高版本,推荐使用replicaof)
replicaof 192.168.31.114 6379
(从Redis 6版本开始,官方更推荐使用replicaof
命令来配置主从复制关系,而不再使用slaveof
命令。这是因为replicaof
更通用,可以用于主从节点之间的数据同步,同时也兼容旧版本的slaveof
命令,以确保向后兼容性。)
3 为Redis创建工作目录
mkdir /usr/local/redis/6379
mkdir /usr/local/redis/6479
mkdir /usr/local/redis/6579
4 启动Redis
执行下面命令启动Redis
redis-server /usr/local/etc/redis-6379.conf
redis-server /usr/local/etc/redis-6479.conf
redis-server /usr/local/etc/redis-6579.conf
使用 ps -ef|grep redis 查看是否都启动成功
连接到主节点客户端
redis-cli -h 127.0.0.1 -p 6379 -a 123456
然后执行 info replication 查看主从复制状态
再以同样的方式查看从节点的信息
到这里主从配置已经完成了
5 哨兵节点配置
拷贝3个配置文件到/usr/local/etc 目录,分别命名为sentinel-26379.conf,sentinel-26479.conf,sentinel-26579.conf,3个配置都一样,主要是需要改一下端口号相关的配置
关键配置如下:
# 端口号
port 26379
# 后台运行程序
daemonize yes
# pid 文件位置
pidfile /usr/local/redis/26379/redis-sentinel.pid
# pid 文件位置
logfile "redis-sentinel.log"
# 监视主节点
sentinel monitor mymaster 192.168.31.114 6379 2
# 主节点密码
sentinel auth-pass mymaster 123456
# 工作目录
dir /usr/local/redis/26379
这里,你是否跟我一样会有疑问,哨兵节点配置中,既没有从节点的信息,哨兵与哨兵之间也没有配置IP地址,他是如何感知这些信息的呢?
当配置Redis Sentinel时,通常需要在哨兵的配置文件中指定要监控的主节点的信息,哨兵通过主节点的信息来发现并监控所有与该主节点关联的从节点。也可以通过主节点发现其他的哨兵节点
6 为哨兵创建工作目录
mkdir /usr/local/redis/26379
mkdir /usr/local/redis/26479
mkdir /usr/local/redis/26579
7 启动哨兵
redis-sentinel /usr/local/etc/sentinel-26379.conf
redis-sentinel /usr/local/etc/sentinel-26479.conf
redis-sentinel /usr/local/etc/sentinel-26579.conf
查看启动日志,cat redis/26379/redis-sentinel.log
到这里,哨兵模式已经安装完成了,也可以查看一下
redis-cli -p 26379 info
# Server
redis_version:6.2.13
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:d2da5754ca5d841b
redis_mode:sentinel
os:Linux 3.10.0-1160.105.1.el7.x86_64 x86_64
arch_bits:64
monotonic_clock:POSIX clock_gettime
multiplexing_api:epoll
atomicvar_api:atomic-builtin
gcc_version:4.8.5
process_id:100545
process_supervised:no
run_id:38d7aa7675140c51d715061f8b3346a30a2a3d06
tcp_port:26379
server_time_usec:1706375512176416
uptime_in_seconds:2064
uptime_in_days:0
hz:12
configured_hz:10
lru_clock:11876696
executable:/usr/local/redis-sentinel
config_file:/usr/local/etc/sentinel-26379.conf
io_threads_active:0# Clients
connected_clients:3
cluster_connections:0
maxclients:10000
client_recent_max_input_buffer:16
client_recent_max_output_buffer:0
blocked_clients:0
tracking_clients:0
clients_in_timeout_table:0# CPU
used_cpu_sys:12.650569
used_cpu_user:41.374952
used_cpu_sys_children:0.000000
used_cpu_user_children:0.000000
used_cpu_sys_main_thread:12.584049
used_cpu_user_main_thread:41.273015# Stats
total_connections_received:2509
total_commands_processed:6122
instantaneous_ops_per_sec:7
total_net_input_bytes:210903
total_net_output_bytes:41899
instantaneous_input_kbps:0.24
instantaneous_output_kbps:0.04
rejected_connections:0
sync_full:0
sync_partial_ok:0
sync_partial_err:0
expired_keys:0
expired_stale_perc:0.00
expired_time_cap_reached_count:0
expire_cycle_cpu_milliseconds:725
evicted_keys:0
keyspace_hits:0
keyspace_misses:0
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:0
total_forks:0
migrate_cached_sockets:0
slave_expires_tracked_keys:0
active_defrag_hits:0
active_defrag_misses:0
active_defrag_key_hits:0
active_defrag_key_misses:0
tracking_total_keys:0
tracking_total_items:0
tracking_total_prefixes:0
unexpected_error_replies:0
total_error_replies:0
dump_payload_sanitizations:0
total_reads_processed:6133
total_writes_processed:3626
io_threaded_reads_processed:0
io_threaded_writes_processed:0# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=127.0.0.1:6379,slaves=4,sentinels=3
8 验证
kill 掉 6379的master节点
执行下面语句,过一会我们将会看到status 从sdown 变成了ok,端口也从6379变成了6579
redis-cli -p 26379 info Sentinel
然后我们再登录6479服务看看,执行下面语句,在执行info replication,可以看到
redis-cli -p 6579 -a 123456
四、SpringBoot 集成Redis客户端
1 添加依赖
目前在Spring官网提供了Spring Data 项目将Redis已经自动集成到SpringBoot项目中,只需要我们添加相关依赖就行了,这里SpringBoot给我们管理的lettuce依赖版本为 6.2.7.RELEASE,所以Redis 版本我们选择6.2.x即可,参考Lettuce官网支持Redis版本范围: Lettuce Reference Guide
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
这里我发现一个小插曲,在Redis的官网推荐是Jedis,参考:Java guide | Redis,然而SpringBoot推荐的是lettuce Spring Data Redis(当然SpringBoot 对于Jedis 和lettuce都提供了驱动),至于2者的对比,参考Spring官网:Spring Data Redis 和我这里问了一下ChatGPT
(另外还有一个常用的Redission,暂时先放一放)
2 添加启动配置
这里我推荐使用Java代码形式的配置,而不是之间使用SpringBoot提供的application.yml 配置形式,这样配置的优点:
- 可以更加接近源码,让我们在用的过程中更加清楚的知道Redis底层的实现方式
- 可以更加细粒度的配置我们想要的方式
缺点
- 操作麻烦,不如直接在application.yml配置方便
- 没有application.yml统一
添加到application.yml
redis-sentinel:
master: mymaster
nodes: 192.168.31.114:26379,192.168.31.114:26479,192.168.31.114:26579
password: 123456
新增RedisSentinelProperties配置文件映射类
package com.ychen.goodscenter.redis;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties(prefix = "redis-sentinel")
@Getter
@Setter
public class RedisSentinelProperties {
private String master;
private String nodes;
private String password;
}
新增RedisConfig 配置类
package com.ychen.goodscenter.redis;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
@Configuration
class RedisConfig {
@Autowired
private RedisSentinelProperties redisSentinelProperties;
@Bean
public RedisSentinelConfiguration redisSentinelConfiguration() {
RedisSentinelConfiguration sentinelConfig = new RedisSentinelConfiguration()
.master(redisSentinelProperties.getMaster());
String[] nodes = redisSentinelProperties.getNodes().split(",");
for (String node : nodes) {
String[] parts = node.split(":");
sentinelConfig.sentinel(parts[0], Integer.parseInt(parts[1]));
}
sentinelConfig.setPassword(redisSentinelProperties.getPassword());
return sentinelConfig;
}
}
3 添加测试类
package com.ychen.goodscenter;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.StringRedisTemplate;
@SpringBootTest
public class RedisTest {
@Autowired
private StringRedisTemplate redisTemplate;
@Test
public void addLink() {
redisTemplate.opsForValue().set("a","33333");
System.out.println(redisTemplate.opsForValue().get("a"));
}
}
执行看看,已经成功的通过哨兵模式访问到Redis