PS:关于集群部署、哨兵模式配置等等后续会陆续补充,当前仅针对redis部署及简单配置使用以及Another.Redis.Desktop.Manager客户端的连接。
我的Centos版本: CentOS 8.0 64位
我下载的redis版本:redis-6.0.1 【不同版本目录可能有些不同,不过基本原理都一样】
yum install gcc-c++
cd /usr/local/redis
wget http://download.redis.io/releases/redis-6.0.1.tar.gz
tar -zxvf redis-6.0.1.tar.gz
make
make install
注意:redis主要工具文件都在src目录下,如: redis-server,redis-cli,redis-benchmark,redis-check-aof,redis-check-rdb,redis-sentinel
这时可以先起服验证一下
起服:redis-server redis.conf
打开cli客户端:redis-cli
ping一下打印出PONG说明安装成功了
阿里云服务器上装redis,推荐不要关闭防火墙,只需要新增安全组规则6379
开启远程链接
:到安装目录cd /usr/local/redis/redis-6.0.1下修改配置文件redis.confvi redis.conf
protected-mode no
daemonize yes
变为后台启动requirepass foobared
前的“#”去掉,foobared改为你想要设置的密码即可这样上面的配置就直接生效了,当然也可以带参数起服,也可以达到同样效果
redis-server redis.conf
redis-cli
auth 密码
或直接输入:redis-cli -a 密码
set name "test"
get name
redis-cli shutdown
`这里小编强烈推荐windows客户端工具《Another.Redis.Desktop.Manager》,不要用《RedisDesktopManager》, 经过对比,前者十分好用
废话少说直接上图,如何配置小编已经在图中标注好了
链接成功后看一下咱们上面设置的test值把
小知识点:Redis 多路复用【本制轮询API】, 单线程、高并发使用非阻塞IO
假设我有三个redis实例,地址分别如下【小编资源有限,用一个虚拟机配置了,大家了解原理即可,也可以多个虚拟机玩】
192.168.91.128:6379
192.168.91.128:6380
192.168.91.128:6381
port 6379
pidfile /var/run/redis_6379.pid
logfile "6379.log"
# RDB 快照文件
dbfilename dump6379.rdb
# AOF 命令备份文件
appendfilename "appendonly6379.aof"
[root@localhost redis-4.0.8]# redis-server redis6379.conf
[root@localhost redis-4.0.8]# redis-server redis6380.conf
[root@localhost redis-4.0.8]# redis-server redis6381.conf
[root@localhost redis-4.0.8]# redis-cli -p 6379
[root@localhost redis-4.0.8]# redis-cli -p 6380
[root@localhost redis-4.0.8]# redis-cli -p 6381
127.0.0.1:6381> SLAVEOF 127.0.0.1 6379
OK
这一步也可以通过在两个从机的 redis.conf
中添加如下配置来解决:
将# replicaof
注释放开,改成主机IP PORT
replicaof 127.0.0.1 6379
redis.conf
# masterauth
注释放开,改成自己密码如下masterauth 密码
INFO replication
命令可以查看每个实例当前的状态,如下: 3127.0.0.1:6379> INFO replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=56,lag=1
slave1:ip=127.0.0.1,port=6381,state=online,offset=56,lag=0
master_replid:26ca818360d6510b717e471f3f0a6f5985b6225d
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:56
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:56
master 都有一个 replication ID
, 当有数据改变时,记录偏移量
,发送给 slave,步骤如下:
一主二仆的主从复制
6380 此时的角色是一个从机,它的主机是 6379,但是 6380 自己也有一个从机,那就是 6381.
按照前面的主从机制,如果master宕机了,就没有master了,可以通过哨兵模式解决群龙无首问题。
sentinel.conf
文件,做如下配置:
其中 mymaster 是给要监控的主机取的名字,随意取,后面是主机地址,最后面的 2 表示有多少个 sentinel 认为主机挂掉了,就进行切换(我这里只有一个,因此设置为1)
注意:
1. 所有的实例均配置 masterauth (在 redis.conf 配置文件中)
2. 所有实例均需要配置绑定地址【自己的服务IP】:bind 192.168.91.128 , 否则java客户端连接会有问题
3. 另外,哨兵配置的时候,监控的 master 也不要直接写 127.0.0.1,按如下方式写
sentinel monitor mymaster 127.0.0.1 6379 1
redis-sentinel sentinel.conf
启动前面配置好的三个 redis 实例,同时启动哨兵
public class Sentinel {
public static void main(String[] args) {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(10);
config.setMaxWaitMillis(1000);
String master = "mymaster";
Set<String> sentinels = new HashSet<>();
sentinels.add("192.168.91.128:26379");
JedisSentinelPool sentinelPool = new JedisSentinelPool(master,
sentinels, config, "javaboy");
Jedis jedis = null;
while (true) {
try {
jedis = sentinelPool.getResource();
String k1 = jedis.get("k1");
System.out.println(k1);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (jedis != null) {
jedis.close();
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
PS: 多个哨兵 nodes 用逗号隔开
spring:
redis:
password: javaboy
timeout: 5000
sentinel:
master: mymaster
nodes: 192.168.91.128:26379
@SpringBootTest
class SentinelApplicationTests {
@Autowired
StringRedisTemplate redisTemplate;
@Test
void contextLoads() {
while (true) {
try {
String k1 = redisTemplate.opsForValue().get("k1");
System.out.println(k1);
} catch (Exception e) {
} finally {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
Redis 集群架构如下图:
Redis 集群运行原理如下:
投票过程是集群中所有 master 参与,如果半数以上 master 节点与 master 节点通信超过 cluster-node-timeout 设置的时间,认为当前 master 节点挂掉。
1.如果集群任意 master 挂掉,且当前 master 没有 slave, 集群进入 fail 状态,也可以理解成集群的 slot 映射 [0-16383] 不完整时进入 fail 状态。
2.如果集群超过半数以上 master 挂掉,无论是否有 slave ,集群进入 fail 状态,当集群不可用时,所有对集群的操作做都不可用,收到 ((error) CLUSTERDOWN The cluster is down) 错误。
Redis 集群管理工具 redis-trib.rb 依赖 ruby 环境,首先需要安装 ruby 环境:
注意:5版本后redis不需要安装ruby, 后文中命令./redis-trib.rb 是指ruby命令,如果redis5版本改为 redis-cli --cluster
yum install ruby
yum install rubygems
但是这种安装方式装好的 ruby 版本可能不适用,如果安装失败,可以参考这篇文章解决 redis requires Ruby version >= 2.2.2。
首先我们对集群做一个简单规划,假设我的集群中一共有三个节点,每个节点一个主机一个从机,这样我一共需要 6 个 Redis 实例。首先创建 redis-cluster 文件夹,在该文件夹下分别创建 7001、7002、7003、7004、7005、7006 文件夹,用来存放我的 Redis 配置文件,如下:
将 Redis 也在 redis-cluster 目录下安装一份,然后将 redis.conf 文件向 7001-7006 这 6 个文件夹中分别拷贝一份,拷贝完成后,分别修改如下参数:
port 7001
#bind 127.0.0.1
cluster-enabled yes
cluster-config-XX XXX7001.conf
protected no
daemonize yes
这时 7001 目录下的配置,其他的文件夹将 7001 改为对应的数字即可。修改完成后,进入到 redis 安装目录中,分别启动各个 redis ,使用刚刚修改过的配置文件,如下:
启动成功后,我们可以查看 redis 进程,如下:
这个表示各个节点都启动成功了。接下来我们就可以进行集群的创建了,首先将 redis/src 目录下的 redis-trib.rb 文件拷贝到 redis-cluster 目录下,然后在 redis-cluster 目录下执行如下命令:
./redis-trib.rb 是指ruby命令,如果redis5版本改为 redis-cli --cluster
./redis-trib.rb create --replicas 1 192.168.248.128:7001 192.168.248.128:7002 192.168.248.128:7003 192.168.248.128:7004 192.168.248.128:7005 192.168.248.128:7006
注意,replicas 后面的 1 表示每个主机都带有 1 个从机,执行过程如下:
注意创建过程的日志,每个 redis 都获得了一个编号,同时日志也说明了哪些实例做主机,哪些实例做从机,每个从机的主机是谁,每个主机所分配到的 hash 槽范围等等。
集群创建成功后,我们可以登录到 Redis 控制台查看集群信息,注意登录时要添加 -c 参数,表示以集群方式连接,如下:
首先我们准备一个端口为 7007 的主节点并启动,准备方式和前面步骤一样,启动成功后,通过如下命令添加主节点:
./redis-trib.rb 是指ruby命令,如果redis5版本改为 redis-cli --cluster
./redis-trib.rb add-node 127.0.0.1:7007 127.0.0.1:7001
主节点添加之后,我们可以通过 cluster nodes 命令查看主节点是否添加成功,此时我们发现新添加的节点没有分配到 slot ,如下:
没有分配到 slot 将不能存储数据,此时我们需要手动分配 slot,分配命令如下:
./redis-trib.rb reshard 127.0.0.1:7001
后面的地址为任意一个节点地址,在分配的过程中,我们一共要输入如下几个参数:
1.一共要划分多少个 hash 槽出来?就是我们总共要给新添加的节点分多少 hash 槽,这个参数依实际情况而定,如下:
2.这些划分出来的槽要给谁,这里输入 7007 节点的编号,如下:
3.要让谁出血?因为 hash 槽目前已经全部分配完毕,要重新从已经分好的节点中拿出来一部分给 7007 ,必然要让另外三个节点把吃进去的吐出来,这里我们可以输入多个节点的编号,每次输完一个点击回车,输完所有的输入 done 表示输入完成,这样就让这几个节点让出部分 slot,如果要让所有具有 slot 的节点都参与到此次 slot 重新分配的活动中,那么这里直接输入 all 即可,如下:
OK,主要就是这几个参数,输完之后进入到 slot 重新分配环节,分配完成后,通过 cluster nodes 命令,我们可以发现 7007 已经具有 slot 了,如下:
OK,刚刚我们是添加主节点,我们也可以添加从节点,比如我要把 7008 作为 7007 的从节点,添加方式如下:
./redis-trib.rb add-node --slave --master-id 79bbb30bba66b4997b9360dd09849c67d2d02bb9 192.168.31.135:7008 192.168.31.135:7007
其中 79bbb30bba66b4997b9360dd09849c67d2d02bb9 是 7007 的编号。
./redis-trib.rb del-node 127.0.0.1:7005 4b45eb75c8b428fbd77ab979b85080146a9bc017
注意 4b45eb75c8b428fbd77ab979b85080146a9bc017 是要删除节点的编号。
再注意:删除已经占有 hash 槽的结点会失败,报错如下:
[ERR] Node 127.0.0.1:7005 is not empty! Reshard data away and try again.
需要将该结点占用的 hash 槽分配出去(分配方式与上文一致,不赘述)。
public class RedisCluster {
public static void main(String[] args) {
Set<HostAndPort> nodes = new HashSet<>();
nodes.add(new HostAndPort("192.168.91.128", 7001));
nodes.add(new HostAndPort("192.168.91.128", 7002));
nodes.add(new HostAndPort("192.168.91.128", 7003));
nodes.add(new HostAndPort("192.168.91.128", 7004));
nodes.add(new HostAndPort("192.168.91.128", 7005));
nodes.add(new HostAndPort("192.168.91.128", 7006));
nodes.add(new HostAndPort("192.168.91.128", 7007));
JedisPoolConfig config = new JedisPoolConfig();
//连接池最大空闲数
config.setMaxIdle(300);
//最大连接数
config.setMaxTotal(1000);
//连接最大等待时间,如果是 -1 表示没有限制
config.setMaxWaitMillis(30000);
//在空闲时检查有效性
config.setTestOnBorrow(true);
JedisCluster cluster = new JedisCluster(nodes, 15000, 15000, 5,
"javaboy", config);
String set = cluster.set("k1", "v1");
System.out.println(set);
String k1 = cluster.get("k1");
System.out.println(k1);
}
}
好了,redis 集群搭建我们先说这么多,有问题欢迎留言讨论。
配置为自己IP后报错:redis Could not connect to Redis at 127.0.0.1:6379: Connection refused
将 bind 127.0.0.1 改为 bind 自己IP 127.0.0.1
模式,不过后来小编把这也注释掉了,原因还没来得及查,大家可以研究一下。
解决:编辑/etc/resolv.conf文件:
vim /etc/resolv.conf
增加Google的DNS服务器IP:
#google域名服务器
nameserver 8.8.8.8
nameserver 8.8.4.4
解决redis desktop manager连接不上linux(centos8)上的redis服务;redis服务已启动,但是用redis desktop manager就是连接不上。
导致原因可能有以下几种:
1. 防火墙禁止了redis端口,可以配置防火墙6379端口, 对于阿里云用户可以配置安全组
2. Redis.conf 下 bind127.0.0.1要注释掉
3. Redis.conf 下 requirepass foobared配置密码
参考网友博客大家可以看一下: https://blog.csdn.net/qq_41986312/article/details/90903197?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1
vm.overcommit_memory | 含义 |
---|---|
0 | 表示内核将检查是否有足够的可用内存。如果有足够的可用内存,内存申请通过,否则内存申请失败,并把错误返回给应用进程 |
1 | 表示内核允许超量使用内存直到用完为止; 注意:本文的可用内存代表物理内存与swap之和。 |
2 | 表示内核决不过量的(“never overcommit”)使用内存,即系统整个内存地址空间不能超过swap+50%的RAM值,50%是overcommit_ratio默认值,此参数同样支持修改 |
(error) MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persist on disk. Commands that may modify the data set are disabled, because this instance is configured to report errors during writes if RDB snapshotting fails (stop-writes-on-bgsave-error option). Please check the Redis logs for details about the RDB error.
# WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the
command 'sysctl vm.overcommit_memory=1' for this to take effect.
vi /etc/sysctl.conf
vm.overcommit_memory=1
或者 sysctl vm.overcommit_memory=1
sysctl -p
使新的参数生效松哥:http://www.javaboy.org/2019/0615/redis-cluster.html
如果对你有帮助,支持一下吧,嘿嘿