一)进行测试Sentinel池:
@Controller public class RestController { @RequestMapping("/Java100") @ResponseBody public String start(){ //1.配置信息 HashSet<String> set=new HashSet<>(); // 连接信息 ip:port // set.add("127.0.0.1:27001"); set.add("124.71.136.248:27001"); //2.创建Sentinel连接池 JedisSentinelPool pool = new JedisSentinelPool("mymaster", set, "12503487"); //3.获取到Jedis客户端 Jedis jedis=pool.getResource(); //4.设置元素 jedis.set("name","zhangsan"); String value=jedis.get("name"); return value; } }
public static void main(String[] args) { RedisURI redisURI = RedisURI.builder() .withHost("124.71.136.248") .withPort(6379) .withPassword("12503487") .build(); RedisClient redisClient = RedisClient.create(redisURI); // // 创建 RedisClient // RedisClient redisClient = RedisClient.create("redis://124.71.136.248:7001"); // 获取与 Redis 单节点的连接 StatefulRedisConnection<String, String> connection = redisClient.connect(); // 获取同步命令 RedisCommands<String, String> syncCommands = connection.sync(); // 执行 Redis 命令 syncCommands.set("key", "value"); String value = syncCommands.get("key"); System.out.println("Value: " + value); // 关闭连接 connection.close(); redisClient.shutdown(); }
二)Redis分片集群
主从集群可以应对高并发读的问题,我们的单节点的内存设置不要太高,如果内存占用的过高,那么在做RDB的持久化或者全量同步的时候就会导致大量的IO,性能下降
1)如果写的并发也很多怎么办呢?
2)如果需要进行存储的数据仍然是很多怎么办呢?
主从模式和哨兵模式可以解决高并发读,高可用的问题,但是仍然存在着海量数据存储的问题和高并发写的问题
3)分片集群的特征:
3.1)集群中有多个master,每一个master保存着不同的数据,这样进行存储的数据总量取决于master结点的数量;
3.2)每一个master本身都有多个slave节点
3.3)master相互之间可以做ping命令来进行检测检测彼此的健康状态
Redis会把每一个master节点映射到0-16383一共是16384个插槽上面,查看集群信息的时候就可以看到:
Redis中的key不是和master节点进行绑定的,而是和插槽进行绑定的,redis会根据key的有效部分来进行计算插槽的值,主要是分成两种情况:
1)key中包含{},况且大括号中至少包含一个字符,那么大括号中的部分就是有效部分
2)key中不包含大括号,整个key都是有效部分
假设如果key是num,那么key的有效部分就是num,但是假设key是{kkk}num,那么有效部分就是kkk,计算方法就是利用CRC16算法得到一个哈希值,针对这个16384取余,最后得到的结果一定是在0-16373之间,然后得到一个solt值;
3)因为redis的主节点是有可能出现宕机的情况的,或者是集群扩容增加了节点,或者是集群伸缩,删除了节点,如果一个节点宕机了,那么这个节点上面的数据也就丢失了,而数据如果是和插槽绑定的,那么当节点宕机的时候,我们可以把对应的插槽转移到正常的节点,集群扩容的时候,也可以将插槽进行转移,这样数据跟着插槽走,就永远可以找到数据的位置
一)Redis是如何进行判断Key在哪一个实例上面?
1)将16384个插槽分配到不同的实例上面
2)根据key的有效部分来计算哈希值,对16384进行取余操作
3)将余数作为插槽,寻找到插槽所在的实例即可
二)如何将同一类数据固定的保存到同一个Redis实例中呢
假设我现在有不同的商品,空调洗衣机手机,各种类型不同的产品,就是将相同的商品放到同一个节点上面,因为将来用户搜索手机的时候,我就可以去同一个节点查询,避免出现请求重定向,因为重定向还要重新建立连接,性能上会有一定的损耗,
所以说这一类数据使用相同的有效部分,例如说key都是以{typeID}为前缀
三)搭建分片集群
1)在/myredis目录下面创建9001 9002 9003 9004 9005 9006 9007目录,并分别写入redis.conf文件
2)在redis.conf文件中配置下面的信息
port 9001 # 开启集群功能 cluster-enabled yes # 集群的配置文件名称,不需要我们创建,只需要程序员指定位置即可这个文件将来由redis自己维护 cluster-config-file /myredis/9001/nodes.conf # 节点心跳失败的超时时间,如果集群之间相互做心跳的时候超过5s没有心跳,就认为是疑似宕机了 cluster-node-timeout 5000 # 持久化文件存放目录 dir /myredis/9001 # 绑定地址,任何地址都可以访问 bind 0.0.0.0 # 让redis后台运行 daemonize yes # 注册的实例ip replica-announce-ip 124.71.136.248 # 保护模式 protected-mode no # 数据库数量 databases 1 # 日志 logfile /myredis/9001.log
3)启动各个目录下面的redis,虽然此时6个redis实例,全部启动起来了,但是它们彼此之间并没有相互联系起来,因为并没有进行指定谁和谁之间是有联系的
创建集群:
1)redis-cli --cluster create --cluster-replicas 1 124.71.136.248:9001 124.71.136.248:9002 124.71.136.248:9003 124.71.136.248:9004 124.71.136.248:9005 124.71.136.248:9006
2)redis-cli -p 9001 cluster nodes3)redis-cli --cluster create 127.0.0.1:9001 127.0.0.1:9002 127.0.0.1:9003 127.0.0.1:9004 127.0.0.1:9005 127.0.0.1:9006
1.1)这里面的redis-cli --cluster代表的是集群操作命令
1.2)create代表的是创建集群
1.3)
port 9001 # 开启集群功能 cluster-enabled yes cluster-node-timeout 5000 cluster-announce-ip 127.0.0.1 cluster-announce-port 9001 # 集群的配置文件名称,不需要我们创建,由redis自己维护 cluster-config-file /myredis/9001/nodes.conf # 节点心跳失败的超时时间 cluster-node-timeout 5000 # 持久化文件存放目录 dir /myredis/9001 # 绑定地址 bind 0.0.0.0 # 让redis后台运行 daemonize yes # 注册的实例ip replica-announce-ip 127.0.0.1 # 保护模式 protected-mode no # 数据库数量 databases 1 # 日志 logfile /myredis/9001.log ~