Redis进阶
Sentinel
redis中master宕机了,我们就要从其它slave中选取一个出来当master,这个时候就有Sentinel了,Sentinel中的哨兵开始执行职责了
哨兵
哨兵(sentinel) 是一个分布式系统,用于对主从结构中的每台服务器进行监控,当出现故障时通过投票机制选择新的master并将所有slave连接到新的master。
哨兵的作用
监控master和slave,不断的检查master和slave是否正常运行,master存活检测、master与slave运行情况检测
当被监控的服务器出现问题时,向其他(哨兵间,客户端)发送通知
断开master与slave连接,选取一个slave作为master,将其他slave连接新的master,并告知客户端新的服务器地址
哨兵也是一台redis服务器,只是不提供数据相关服务,通常哨兵的数量配置为单数
哨兵配置
- 设置哨兵监听的主服务器信息, sentinel_number表示参与投票的哨兵数量
1
| sentinel monitor master_name master_host master_port sentinel_number
|
- 设置判定服务器宕机时长,该设置控制是否进行主从切换
1
| sentinel down-after-milliseconds master_name million_seconds
|
1
| sentinel failover-timeout master_name million_seconds
|
- 设置主从切换后,同时进行数据同步的slave数量,数值越大,要求网络资源越高,数值越小,同步时间越长
1
| sentinel parallel-syncs master_name sync_slave_number
|
「sentinel.conf」
1 2 3 4 5 6 7 8
| port 26379 daemonize yes pidfile "/var/run/redis-sentinel26379.pid" logfile "/export/server/sentinel-26379/log/log.log" dir "/export/server/sentinel- 26379/data" sentinel monitor mymaster 0.0.0.0 6379 2 sentinel resolve-hostnames no sentinel announce-hostnames no
|
「配置命令」
1
| ./bin/redis-server redis.conf
|
1
| ./bin/redis-server redis.conf slaveof 主ip 主端口
|
java原生连接sentinel
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
| <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>
<groupId>com.dream.xiaobo</groupId> <artifactId>redis_operation</artifactId> <version>1.0-SNAPSHOT</version>
<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> <scope>test</scope> </dependency> <dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>6.14.3</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.0</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> <!-- <verbal>true</verbal>--> </configuration> </plugin> </plugins> </build>
<properties> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> </properties>
</project>
|
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
| public class RedisSentinelTest {
private JedisSentinelPool jedisSentinelPool;
@BeforeTest public void beforeTest(){
// 配置对象 JedisPoolConfig config = new JedisPoolConfig();
// 最大空闲连接 config.setMaxIdle(10); // 最小空闲连接 config.setMinIdle(5);
// 连接时最大等待时间 config.setMaxWaitMillis(3000);
// 最大连接数 config.setMaxTotal(100);
Set<String> sentinel = new HashSet<>();
sentinel.add("152.136.22.223:26379"); sentinel.add("152.136.22.223:26380"); sentinel.add("152.136.22.223:26381");
jedisSentinelPool = new JedisSentinelPool("mymaster",sentinel,config);
}
@Test public void keysTest(){ Jedis jedis = jedisSentinelPool.getResource();
Set<String> keys = jedis.keys("*");
for (String key : keys) { System.out.println(key); }
}
@AfterTest public void afterTest(){ jedisSentinelPool.close(); }
}
|
spring连接sentinel
1 2 3 4 5
| spring: redis: sentinel: nodes: 0.0.0.0:26379,0.0.0.0::26380,0.0.0.0::26381 master: mymaster
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| @SpringBootTest class RedisBootOperationApplicationTests {
@Autowired private RedisTemplate redisTemplate;
@Test void contextLoads() {
redisTemplate.opsForValue().set("name","xiaobo");
Object name = redisTemplate.opsForValue().get("name");
System.out.println(name);
redisTemplate.boundValueOps("age").set(22);
Object age = redisTemplate.boundValueOps("age").get();
System.out.println(age);
}
}
|
Redis集群 Cluster
集群就是使用网络将若干台计算机联通起来,并提供统一的管理方式,使其对外呈现单机的服务效果
集群的作用
- 分散单台服务器的访问压力,实现负载均衡
- 分散单台服务器的存储压力,实现可扩展性
- 降低单台服务器宕机带来的业务灾难
集群搭建
- 配置服务器(3主3从)
- 建立通信(Meet)
- 分槽(Slot)
- 搭建主从(master-slave)
「最少3主」
搭建步骤
1 2 3 4 5 6 7 8 9 10 11
| port 7001 bind 0.0.0.0 protected-mode no daemonize yes pidfile /var/run/redis_7001.pid logfile "/export/server/redis-7001/log/redis.log" dir /export/server/redis-7001/data/ appendonly yes cluster-enabled yes cluster-config-file nodes-7001.conf cluster-node-timeout 15000
|
1
| redis-cli --cluster create 0.0.0.0:7001 0.0.0.0:7002 0.0.0.0:7003 0.0.0.0:7004 0.0.0.0:7005 0.0.0.0:7006 --cluster-replicas 1
|
1
| ./bin/redis-cli --cluster fix 0.0.0.0:端口号
|
输入 yes
1
| ./bin/redis-cli -c -h 0.0.0.0 -p 端口号
|
cluster集群配置
- cluster配置文件名,该文件属于自动生成,仅用于快速查找文件并查询文件内容
1
| cluster-config-file filename
|
- 节点服务响应超时时间,用于判定该节点是否下线或切换为从节点
1
| cluster-node-timeout milliseconds
|
1
| cluster-migration-barrier min_slave_number
|
Cluster节点操作命令
1
| cluster replicate master-id
|
1
| cluster forget server_id
|
集群操作命令
1
| redis-cli –-cluster create masterhost1:masterport1 masterhost2:masterport2 masterhost3:masterport3 [masterhostn:masterportn …] slavehost1:slaveport1 slavehost2:slaveport2 slavehost3:slaveport3 -–cluster-replicas n
|
- 添加master到当前集群中,连接时可以指定任意现有节点地址与端口
1
| redis-cli --cluster add-node new-master-host:new-master-port now-host:now-port
|
1
| redis-cli --cluster add-node new-slave-host:new-slave-port master-host:master-port --cluster-slave --cluster-master-id masterid
|
- 删除节点,如果删除的节点是master,必须保障其中没有槽slot
1
| redis-cli --cluster del-node del-slave-host:del-slave-port del-slave-id
|
- 重新分槽,分槽是从具有槽的master中划分一部分给其他master,过程中不创建新的槽
1
| redis-cli --cluster reshard new-master-host:new-master:port --cluster-from src- master-id1, src-master-id2, src-master-idn --cluster-to target-master-id -- cluster-slots slots
|
- 重新分配槽,从具有槽的master中分配指定数量的槽到另一个master中,常用于清空指定master中的槽
1
| redis-cli --cluster reshard src-master-host:src-master-port --cluster-from src- master-id --cluster-to target-master-id --cluster-slots slots --cluster-yes
|
java原生连接Cluster
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
| public class RedisClusterTest {
private JedisCluster jedisCluster;
@BeforeTest public void beforeTest(){
JedisPoolConfig config = new JedisPoolConfig();
// 最大空闲连接 config.setMaxIdle(10); // 最小空闲连接 config.setMinIdle(5);
// 连接时最大等待时间 config.setMaxWaitMillis(3000);
// 最大连接数 config.setMaxTotal(100);
Set<HostAndPort> nodes = new HashSet<>();
nodes.add(new HostAndPort("152.136.22.223",7001)); nodes.add(new HostAndPort("152.136.22.223",7002)); nodes.add(new HostAndPort("152.136.22.223",7003)); nodes.add(new HostAndPort("152.136.22.223",7004)); nodes.add(new HostAndPort("152.136.22.223",7005)); nodes.add(new HostAndPort("152.136.22.223",7006));
jedisCluster = new JedisCluster(nodes,config);
}
@Test public void test(){
jedisCluster.set("name","xiaobo");
String a = jedisCluster.get("a");
System.out.println(a);
}
@AfterTest public void afterTest(){ try { jedisCluster.close(); } catch (IOException e) { throw new RuntimeException(e); } }
}
|
springboot连接Cluster
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| spring: redis: pool: max-idle: 100 min-idle: 1 max-active: 1000 max-wait: -1 cluster: nodes: - 0.0.0.0:7001 - 0.0.0.0:7002 - 0.0.0.0:7003 - 0.0.0.0:7004 - 0.0.0.0:7005 - 0.0.0.0:7006 database: 0 timeout: 15000 connect-timeout: 5000
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| @SpringBootTest class RedisBootOperationApplicationTests {
@Autowired private RedisTemplate redisTemplate;
@Test void contextLoads() {
redisTemplate.opsForValue().set("name","xiaobo");
Object name = redisTemplate.opsForValue().get("name");
System.out.println(name);
redisTemplate.boundValueOps("age").set(22);
Object age = redisTemplate.boundValueOps("age").get();
System.out.println(age);
}
}
|
「你知道的越多 你不知道的越多 嘿 我是小博 带你一起看我目之所及的世界……」