四、Jedis连接redis服务器
4.1 项目结构
需要导入两个包。
项目结构 |
4.2 Jedis连接redis服务端
package com.xkt.jedis;
import java.util.Set;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import redis.clients.jedis.Jedis;
/**
* @author lzx
*
*/
public class JedisTest {
private Jedis jedis = null;
/**
* new Jedis(host, port, timeout);
*
* host redis所在服务器地址 port 端口 默认6379 timeout 连接超时时间,默认5s
*
* 连接reids注意事项: (1)防火墙问题 (2)Ip绑定。把Redis的配置文件redis.conf里的bind localhost(或者bind
* 127.0.0.1,表明只有该主机才能访问)注释掉。 (3)protected-mode保护模式 如果碰到,将protected-mode改成no即可。
*/
@Before
public void before() {
// 1、创建客户端Jedis
jedis = new Jedis("192.168.109.3", 6379, 5);
// 2.指定密码
jedis.auth("1234");
}
@After
public void after() {
// 关闭资源
if (null != jedis) {
jedis.close();
}
}
/**
* 测试连接
*/
@Test
public void testConn() {
String pong = jedis.ping();
System.out.println(pong);
}
/**
* 获得所有key
*/
@Test
public void getAllKeys() {
Set<String> keys = jedis.keys("*");
for (String key : keys) {
System.out.println(key);
}
}
}
连接reids注意事项:
- 防火墙问题
- Ip绑定。把Redis的配置文件redis.conf里的bind localhost(或者bind 127.0.0.1,表明只有该主机才能访问)注释掉。
- protected-mode保护模式 如果碰到,将protected-mode改成no即可。
五、Redis集群
5.1 Redis集群简介
所谓的集群,就是通过添加服务器的数量,提供相同的服务,从而让服务器达到一个稳定、高效的状态。
- redis集群中,每一个redis称之为一个节点。
- redis集群中,有两种类型的节点:主节点(master)、从节点(slave)。
- redis集群,是基于redis主从复制实现。
5.2 主从复制
5.2.1 主从复制是什么
- 主从复制模型中,有多个redis节点。
- 其中,有且仅有一个为主节点Master。从节点Slave可以有多个。
- 只要网络连接正常,Master会一直将自己的数据更新同步给Slaves,保持主从同步。
模型 |
5.2.2 主从复制的特点
- 主节点Master可读、可写.
- 从节点Slave只读。(read-only)
- 因此,主从模型可以提高读的能力,在一定程度上缓解了写的能力。因为能写仍然只有Master节点一个,可以将读的操作全部移交到从节点上,变相提高了写能力。
5.3 Redis-cluster集群
这里我们介绍Redis-cluster集群,因为哨兵模式当并发写请求较大时,哨兵模式并不能缓解写压力。
我们知道只有主节点才具有写能力,那如果在一个集群中,能够配置多个主节点,是不是就可以缓解写压力了呢?这就引出了我们的redis-cluster集群模式。
5.3.1 Redis-cluster集群概念
- 由多个Redis服务器组成的分布式网络服务集群;
- 集群之中有多个Master主节点,每一个主节点都可读可写;
- 节点之间会互相通信,两两相连;
- Redis集群无中心节点。
图示 |
5.3.2 集群节点复制
图示 |
- 在Redis-Cluster集群中,可以给每一个主节点添加从节点,主节点和从节点直接遵循主从模型的特性。
- 当用户需要处理更多读请求的时候,添加从节点可以扩展系统的读性能。
5.3.3 故障转移
Redis集群的主节点内置了类似Redis Sentinel的节点故障检测和自动故障转移功能,当集群中的某个主节点下线时,集群中的其他在线主节点会注意到这一点,并对已下线的主节点进行故障转移。
图示 |
集群进行故障转移的方法和Redis Sentinel进行故障转移的方法基本一样,不同的是,在集群里面,故障转移是由集群中其他在线的主节点负责进行的,所以集群不必另外使用Redis Sentinel。
5.3.4 集群分片策略
- Redis-cluster分片策略,是用来解决key存储位置的。
- 集群将整个数据库分为16384个槽位slot,所有key-value数据都存储在这些slot中的某一个上。一个slot槽位可以存放多个数据,key的槽位计算公式为:slot_number=crc16(key)%16384,其中crc16为16位的循环冗余校验和函数。
- 集群中的每个主节点都可以处理0个至16383个槽,当16384个槽都有某个节点在负责处理时,集群进入上线状态,并开始处理客户端发送的数据命令请求。
图示 |
5.3.5 集群redirect转向
- 由于Redis集群无中心节点,请求会随机发给任意主节点;
- 主节点只会处理自己负责槽位的命令请求,其它槽位的命令请求,该主节点会返回客户端一个转向错误;
- 客户端根据错误中包含的地址和端口重新向正确的负责的主节点发起命令请求。
图示 |
六、Redis-cluster集群搭建
6.1 准备工作
- 安装ruby环境
- yum -y install ruby
- yum -y install rubygems
- 安装ruby和redis的接口程序
拷贝redis-3.0.0.gem至/usr/local下,执行安装:
- gem install /usr/local/redis-3.0.0.gem
6.2 集群规划
- Redis集群最少需要6个节点,可以分布在一台或者多台主机上。
我们测试采用一台主机上创建伪分布式集群,不同的端口表示不同的redis节点,如下:
- 主节点:192.168.56.3:7001 192.168.56.3:7002 192.168.56.3:7003
- 从节点:192.168.56.3:7004 192.168.56.3:7005 192.168.56.3:7006
- 在/usr/local/redis下创建redis-cluster目录,其下创建7001、7002。。7006目录([root@node redis-cluster]# mkdir 7001 7002 7003 7004 7005 7006),如下:
图示 |
- 将redis解压路径下的配置文件redis.conf,依次拷贝到每个700X目录内,并修改每个700X目录下的redis.conf配置文件:
- 修改bind 为了其他机器也可以访问
- cluster-enabled yes 支持集群
- daemonized yes 后台启动
- logfile /usr/local/redis/redis-cluster/700X/node.log
1>必选配置:
- port 700X
- bind 192.168.56.3
- cluster-enabled yes
2>建议配置: - daemonized yes
- logfile /usr/local/redis/redis-cluster/700X/node.log
6.3 启动每个结点redis服务
- 依次以700X下的redis.conf,启动redis节点。(必须指定redis.conf文件)
到各自文件夹下启动,否则可能启动不了
- redis-server /usr/local/redis/redis-cluster/700X/redis.conf
6.4 执行创建集群命令
- 进入到redis源码存放目录redis/redis-4.10.3/src下,执行redis-trib.rb
- ./redis-trib.rb create --replicas 1 192.168.56.3:7001 192.168.56.3:7002 192.168.56.3:7003 192.168.56.3:7004 192.168.56.3:7005 192.168.56.3:7006
图示 |
6.5 查询集群信息
- 集群创建成功登陆任意redis结点查询集群中的节点情况
- ./redis-cli -c -h 192.168.56.3 -p 7001
图示 |
- 上面命令说明:
- -c表示以集群方式连接redis,
- -h指定ip地址,
- -p指定端口号
- 登陆集群后使用以下命令:
- cluster nodes 查询集群结点信息;
- cluster info 查询集群状态信息。
七、java程序连接redis集群
package com.xkt.redis.test;
import java.util.HashSet;
import java.util.Set;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
/**
* @author lzx
*
*/
public class Test {
public static void main(String[] args) {
//连接jediscluster客户端
String host ="192.168.109.3";
Set<HostAndPort> nodes =new HashSet<>();
nodes.add(new HostAndPort(host, 7001));
nodes.add(new HostAndPort(host, 7002));
nodes.add(new HostAndPort(host, 7003));
nodes.add(new HostAndPort(host, 7004));
nodes.add(new HostAndPort(host, 7005));
nodes.add(new HostAndPort(host, 7006));
JedisCluster cluster = new JedisCluster(nodes);
String name = cluster.hget("user:id:1", "name");
System.out.println(name);
cluster.close();
}
}