当前位置: 首页 > news >正文

兰州网站推广建设郑州住房和城乡建设部网站

兰州网站推广建设,郑州住房和城乡建设部网站,wordpress 在线教育,毕业设计静态网站建设选题依据一、主从复制(replica)#xff08;不推荐#xff09; 介绍 主从复制 mmaster以写为主#xff0c;slave以读为主当master数据变化时#xff0c;自动将新的数据异步同步到其他slave数据库 读写分离down机恢复数据备份水平扩容支撑高并发 基本操作 配从不配主 权限细节 maste…一、主从复制(replica)不推荐 介绍 主从复制 mmaster以写为主slave以读为主当master数据变化时自动将新的数据异步同步到其他slave数据库 读写分离down机恢复数据备份水平扩容支撑高并发 基本操作 配从不配主 权限细节 master如果配置了 requirepass 参数需要密码登录slave 需要配置 masterauth来设置检验密码否则的话master会拒绝slave的访问请求 基本操作命令 info replication 查看复制节点的主从关系和配置信息replicaof/slaveof 主库IP 主库端口 replicaof/slaveof这两个一样一般写入进redis.conf配置文件内在运行期间修改slave节点的信息如果该数据库已经某个数据库的从数据库那么会停止和原主数据库的同步关系转而和新的主数据库同步replicaof/slaveof no one 使当前数据库停止与其他数据库的同步升级为主数据库 配置一个master两个slave 当前环境是在同一个ip下不同端口配置 主master6001.conf #1 Redis默认不是以守护进程的方式运行可以通过该配置项修改使用yes启用守护进程 daemonize yes #2 注释只能本地连接 #bind 127.0.0.1 #3 默认开启保护模式如果没有设置密码或者没有 bind 配置我只允许在本机连接我其它机器无法连接。 protected-mode no port 6001 dir /redis-learn/redis-7.0.9/conf/replica/6001 pidfile redis_6001.pid logfile 6001.log requirepass xgm2023 dbfilename dump6001.rdb #开启aof持久增量存储 appendonly yes appendfilename appendonly6001.aof 从slave16002.conf(拜大哥主机) #1 Redis默认不是以守护进程的方式运行可以通过该配置项修改使用yes启用守护进程 daemonize yes #2 注释只能本地连接 #bind 127.0.0.1 #3 默认开启保护模式如果没有设置密码或者没有 bind 配置我只允许在本机连接我其它机器无法连接。 protected-mode no port 6002 dir /redis-learn/redis-7.0.9/conf/replica/6002 pidfile redis_6001.pid logfile 6002.log requirepass xgm2023 dbfilename dump6001.rdb #开启aof持久增量存储 appendonly yes appendfilename appendonly6002.aof #主从复制主机ip端口 replicaof 172.16.64.21 6001 #主机密码 masterauth xgm2023 从slave26003.conf(拜大哥主机) #1 Redis默认不是以守护进程的方式运行可以通过该配置项修改使用yes启用守护进程 daemonize yes #2 注释只能本地连接 #bind 127.0.0.1 #3 默认开启保护模式如果没有设置密码或者没有 bind 配置我只允许在本机连接我其它机器无法连接。 protected-mode no port 6003 dir /redis-learn/redis-7.0.9/conf/replica/6003 pidfile redis_6003.pid logfile 6003.log requirepass xgm2023 dbfilename dump6003.rdb #开启aof持久增量存储 appendonly yes appendfilename appendonly6003.aof #主从复制主机ip端口 replicaof 172.16.64.21 6001 #主机密码 masterauth xgm2023 注意防火墙配置 启动 systemctl start firewalld 关闭 systemctl stop firewalld 查看状态 systemctl status firewalld 开机禁用 systemctl disable firewalld 开机启用 systemctl enable firewalld 添加 firewall-cmd --zonepublic --add-port80/tcp --permanent –permanent永久生效没有此参数重启后失效 重新载入 firewall-cmd --reload 查看 firewall-cmd --zone public --query-port80/tcp 删除 firewall-cmd --zone public --remove-port80/tcp --permanent 启动 ./redis-server …/conf/replica/redis-masterr-6001.conf ./redis-server …/conf/replica/redis-slaver-6002.conf ./redis-server …/conf/replica/redis-slaver-6003.conf 查看主从关系 info replication 日志查看 主机 从机 复制原理 slave启动同步初请 slave启动成功连接到master后会发送一个sync命令slave首次全新连接master一次完全同步全量复制将被自动执行slave自身原有数据会被master数据覆盖清除 首次连接全量复制 master节点收到sync命令后会在后台开始保存快照即RDB持久化主从复制会触发RDB同时收集所有接收到的用于修改数据集命令缓存起来master节点执行RDB持久化后master将rdb快照文件和缓存的命令发送到所有slave已完成一次完全同步而slave服务在接收到数据库文件数据后将其存盘并加载到内存中从而完成复制初始化 心跳持续保持通信 repl-ping-replica-period 10master发出PING包的周期默认是10秒 进入平稳增量复制 master 继续将新的所有收集到的修改命令自动一次传给slave完成同步 从机下线重连续传 master 会检查backlog里面的offsetmaster和slave都会保存一个复制的offset怀有一个masterIdoffset 是保存在backlog 中的。master只会把已经复制的offset后面的数据赋值给slave类似断电续传 缺点 复制延时信号衰减 由于所有的写操作都是先在Master上操作然后同步更新到Slave上所以从Master同步到Slave机器有一定的延迟当系统很繁忙的时候延迟问题会更加严重Slave机器数量的增加也会使这个问题更加严重。 master挂了 默认情况下不会在slave节点自动重选一个master需要人工干预 二、哨兵(sentinel)(不推荐) 介绍 哨兵巡查监控后台master主机是否故障如果故障了根据投票数自动将某一个从库转换为新主库继续对外服务俗称无人值守运维不存放数据只是吹哨人 作用 监控redis运行状态包括master和slave当master down机能自动将slave切换成新master 哨兵的四个功能 主从监控 监控主从redis库运行是否正常 消息通知 哨兵可以将故障转移的结果发送到客户端 故障转移 如果master异常则会进行主从切换将其中一个slave作为新master 配置中心 客户端通过连接哨兵来获得当前Redis服务的主节点地址 搭建 redis配置成奇数好投票 哨兵本身也要配置集群不然也是单点故障 哨兵6004 sentinel.conf bind 0.0.0.0 logfile /redis-learn/redis-7.0.9/conf/sentinel/6004/6004.log pidfile /redis-learn/redis-7.0.9/conf/sentinel/6004/redis-sentinel-6004.pid dir /redis-learn/redis-7.0.9/conf/sentinel/6004/ protected-mode no daemonize no port 6004 #设置要监控的redis master2表示最少有几个哨兵认可客观下线同意故障迁移的法定票数 sentinel monitor mymaster 172.16.64.21 6001 2 #sentinel访问master密码 sentinel auth-pass mymaster xgm2023哨兵6005 sentinel.conf bind 0.0.0.0 logfile /redis-learn/redis-7.0.9/conf/sentinel/6005/6005.log pidfile /redis-learn/redis-7.0.9/conf/sentinel/6005/redis-sentinel-6005.pid dir /redis-learn/redis-7.0.9/conf/sentinel/6005/ protected-mode no daemonize no port 6005 #设置要监控的redis master2表示最少有几个哨兵认可客观下线同意故障迁移的法定票数 sentinel monitor mymaster 172.16.64.21 6001 2 #sentinel访问master密码 sentinel auth-pass mymaster xgm2023哨兵6006 sentinel.conf bind 0.0.0.0 logfile /redis-learn/redis-7.0.9/conf/sentinel/6006/6006.log pidfile /redis-learn/redis-7.0.9/conf/sentinel/6006/redis-sentinel-6006.pid dir /redis-learn/redis-7.0.9/conf/sentinel/6006/ protected-mode no daemonize no port 6006 #设置要监控的redis master2表示最少有几个哨兵认可客观下线同意故障迁移的法定票数 sentinel monitor mymaster 172.16.64.21 6001 2 #sentinel访问master密码 sentinel auth-pass mymaster xgm2023主从复制一主2从 当前主从复制和上面搭建的一样除了主机也要配置masterauth xgm2023因为6001可能挂机后变成从机 修改6001.conf masterauth xgm2023启动主从复制集群 ./redis-server …/conf/replica/redis-master-6001.conf ./redis-server …/conf/replica/redis-slaver-6002.conf ./redis-server …/conf/replica/redis-slaver-6003.conf 启动三个哨兵 ./redis-sentinel …/conf/sentinel/sentinel6004.conf --sentinel ./redis-sentinel …/conf/sentinel/sentinel6005.conf --sentinel ./redis-sentinel …/conf/sentinel/sentinel6006.conf --sentinel 故障迁移演示 查看集群关系此时6001是master 关闭master 6001 结论 6002变为mster数据不会丢失 重启6001 结论 6001不能切换为主master还是之前的6002为master 哨兵选举原理 当一个主从配置中的master失效之后sentinel可以选举出一个新的master用于接替原master的工作主从配置中其他redis服务器自动指向新的master同步数据。一般建议sentinel采用奇数台防止某一台sentinel无法连接到master导致误切换、 SDOWN主观下线 SDOWN 是单个sentinel 自己主观上检测到的关于master的状态从sentinel的角度来看如果发送了PING心跳后在一定时间内没有收到合法的回复就达到了SDOWN的条件sentinel配置文件中的down-after-milliseconds 设置了判断主观下线的时间长度 ODOWN客观下线 ODOWN需要一定数量的sentinel多个哨兵达成一致意见才能认为一个master客观上已经宕机 选举出领导者哨兵 当主节点被判断客观下线以后各个哨兵节点会进行协商县选举出一个领导者哨兵节点并由该领导者节点进行failover故障迁移Raft算法 选出领导者节点 由领导者节点开始推动故障切换并选出一个新master 新主登基 某个slave 备选成为新 master 群臣俯首 一朝天子一朝臣重新认老大 旧主拜服 老master回来也得怂 以上的failover都是sentinel自己独立完成完全无需人工干预 使用建议 哨兵节点的数量应为多个哨兵本身应该集群保证高可用哨兵节点的数量应该是奇数个各个哨兵节点的配置应该一致如果哨兵节点部署在Docker等容器里要注意端口的正确映射哨兵集群主从复制并不能保证数据零丢失 springboot使用 踩坑 注意 redis.conf配置文件中的replicaof 具体ip而不是127.0.0.1不然哨兵连接报错 sentinel.conf中的mymaster主机IP也要具体指定 读写分离配置 pom文件 ?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersionparentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.7.17/versionrelativePath/ !-- lookup parent from repository --/parentgroupIdcom.redis/groupIdartifactIdredis-sentinel/artifactIdversion0.0.1-SNAPSHOT/versionnameredis-sentinel/namedescriptionredis-sentinel/descriptionpropertiesjava.version1.8/java.version/propertiesdependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-devtools/artifactIdscoperuntime/scopeoptionaltrue/optional/dependencydependencygroupIdcom.mysql/groupIdartifactIdmysql-connector-j/artifactIdscoperuntime/scope/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependencydependencygroupIdorg.apache.commons/groupIdartifactIdcommons-pool2/artifactId/dependency/dependenciesbuildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactIdconfigurationexcludesexcludegroupIdorg.projectlombok/groupIdartifactIdlombok/artifactId/exclude/excludes/configuration/plugin/plugins/build/project 配置文件 #连接数据源 spring.datasource.druid.usernameroot spring.datasource.druid.passwordxgm2023.. spring.datasource.druid.urljdbc:mysql://172.16.204.51:3306/redis?serverTimezoneGMT%2B8 spring.datasource.druid.driver-class-namecom.mysql.cj.jdbc.Driver spring.datasource.druid.initial-size5#redis哨兵模式 spring.redis.sentinel.mastermymaster #哨兵集群 spring.redis.sentinel.nodes172.16.64.21:6004,172.16.64.21:6005,172.16.64.21:6006 spring.redis.database0 spring.redis.passwordxgm2023 spring.redis.timeout3000ms #默认的lettuce lettuce线程安全Jedis是同步的不支持异步Jedis客户端实例不是线程安全的需要每个线程一个Jedis实例所以一般通过连接池来使用Jedis. # 连接池最大连接数使用负值表示没有限制 spring.redis.lettuce.pool.max-active100 # 连接池中的最大空闲连接 spring.redis.lettuce.pool.max-idle100 # 连接池最大阻塞等待时间使用负值表示没有限制 spring.redis.lettuce.pool.max-wait1000ms # 连接池中的最小空闲连接 spring.redis.lettuce.pool.min-idle1 spring.redis.lettuce.shutdown-timeout1000ms#日志 logging.pattern.console%date{yyyy-MM-dd HH:mm:ss.SSS} | %highlight(%5level) [%green(%16.16thread)] %clr(%-50.50logger{49}){cyan} %4line -| %highlight(%msg%n) logging.level.rootinfo logging.level.io.lettuce.coredebug logging.level.org.springframework.data.redisdebug读写分离配置 package com.redis.redissentinel.conf; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import io.lettuce.core.ReadFrom; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.data.redis.RedisProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisPassword; import org.springframework.data.redis.connection.RedisSentinelConfiguration; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.HashSet; import java.util.TimeZone; import org.springframework.data.redis.core.RedisTemplate; /*** author ygr* date 2022-02-15 16:30*/ Slf4j Configuration public class RedisConfig {public ObjectMapper objectMapper() {ObjectMapper objectMapper new ObjectMapper();objectMapper.setTimeZone(TimeZone.getTimeZone(GMT8));objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);objectMapper.setDateFormat(new SimpleDateFormat(yyyy-MM-dd HH:mm:ss));objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);return objectMapper;}BeanConditionalOnMissingBeanpublic RedisTemplateString, Object redisTemplate(RedisConnectionFactory factory) {// 创建RedisTemplateString, Object对象RedisTemplateString, Object template new RedisTemplate();template.setConnectionFactory(factory);// 定义Jackson2JsonRedisSerializer序列化对象Jackson2JsonRedisSerializerObject jackson2JsonRedisSerializer new Jackson2JsonRedisSerializer(Object.class);jackson2JsonRedisSerializer.setObjectMapper(objectMapper());StringRedisSerializer stringSerial new StringRedisSerializer();// redis key 序列化方式使用stringSerialtemplate.setKeySerializer(stringSerial);// redis value 序列化方式使用jacksontemplate.setValueSerializer(jackson2JsonRedisSerializer);// redis hash key 序列化方式使用stringSerialtemplate.setHashKeySerializer(stringSerial);// redis hash value 序列化方式使用jacksontemplate.setHashValueSerializer(jackson2JsonRedisSerializer);template.afterPropertiesSet();return template;}Beanpublic RedisConnectionFactory lettuceConnectionFactory(RedisProperties redisProperties) {RedisSentinelConfiguration sentinelConfig new RedisSentinelConfiguration().master(redisProperties.getSentinel().getMaster());redisProperties.getSentinel().getNodes().forEach(s - {String[] arr s.split(:);sentinelConfig.sentinel(arr[0],Integer.parseInt(arr[1]));});LettucePoolingClientConfiguration lettuceClientConfiguration LettucePoolingClientConfiguration.builder()// 读写分离若主节点能抗住读写并发则不需要设置全都走主节点即可//ANY 从任何节点读取,NEAREST 从最近节点读取,MASTER_PREFERRED / UPSTREAM_PREFERRED优先读取主节点如果主节点不可用则读取从节点,MASTER / UPSTREAM仅读取主节点.readFrom(ReadFrom.ANY_REPLICA).build();sentinelConfig.setPassword(RedisPassword.of(redisProperties.getPassword()));sentinelConfig.setDatabase(redisProperties.getDatabase());return new LettuceConnectionFactory(sentinelConfig, lettuceClientConfiguration);}}测试 package com.redis.redissentinel;import lombok.extern.slf4j.Slf4j; 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.RedisTemplate;import javax.annotation.Resource; import java.util.concurrent.TimeUnit;Slf4j SpringBootTest class RedisSentinelApplicationTests {Resourceprivate RedisTemplateString, Object redisTemplate;Testvoid witeTest() {for (int i 0; i 3; i) {try {redisTemplate.opsForValue().set(k i, v i);log.info(set value success: {}, i);Object val redisTemplate.opsForValue().get(k i);log.info(get value success: {}, val);TimeUnit.SECONDS.sleep(1);} catch (Exception e) {log.error(error: {}, e.getMessage());}}log.info(finished...);}Testvoid readTest() {Object k1 redisTemplate.opsForValue().get(k1);log.info(读取节点k1的值{},k1);}} 踩坑指南 1 redis哨兵相关配置指定具体的ip不要写127.0.0.1 1可以写进/etc/hosts 比如 172.16.64.21 redis6001 2如果是多个服务器地址相互在hots指定 2 配置安全线程池必须在pom文件引入commons-pool2这个包 3 在redisconfig配置中必须设置sentinelConfig.setPassword(RedisPassword.of(redisProperties.getPassword())); 不然会报错 NOAUTH HELLO must be called with the client already authenticated, otherwise the HELLO AUTH 三、cluster(重点/推荐) 官网介绍 https://redis.io/docs/reference/cluster-spec/ 架构图 1 cluster主节点挂了slave顶替上来自己挂了不影响其他主节点的使用 2 redis集群支持多个master每个master又可以挂在多个slave 3 cluster自带sentinel故障转移机制内置了高可用支持无需再去使用哨兵功能 4 客户端与redis的节点连接不再需要连接集群中所有的节点只需要任意连接集群中的一个可用节点即可 5 槽位slot负责分配到各个物理服务节点由对应集群来负责维护节点、插槽和数据之间的关系 架构设计原理 16384个slot卡槽16384主节点但建议最大主节点不要超过1000 redis集群槽位图 redis集群优点 1 方便扩缩容和数据分派查找 扩缩容节点的移动并不会停止服务改变节点哈希槽的数量都不会造成集群不可用的状态 slot槽位映射 哈希槽取余(不推荐) hash(key)% 机器数 适用场景 小厂/公司 不会变动机器数量 优点 简单粗暴直接有效起到负载均衡分而治之的作用 缺点 进行扩容和缩容比较麻烦映射关系重新计算宕机会导致hash取余全部数据重新洗牌原来的值存在服务器但获取不到也就是数据丢失(虽然存在服务器但找不到) 一致性哈希算法分区(不推荐) ip节点映射和 落键规则 hash(key)% 2^32-1 适用场景 中小公司 优点 具备容错性和扩张性 加入和删除节点只影响哈希环中顺时针方向相邻的节点对其他节点无影响缺点 数据倾斜头重脚轻分布不均匀 哈希槽分区(16384卡槽推荐) 0~2^14-1 16384 哈希槽实质就是一个数组数组[0,16383]形成的hash slot CRC16(key) % 16384 适用场景 大厂 优点 均匀分布,负载均衡 缺点 源码 public static void main(String[] args) {//哈希槽大小SlotHash.SLOT_COUNT16384,HashMap// end CRC16.crc16(key.array(), key.position(), key.limit() - key.position()) % 16384;int a SlotHash.getSlot(A);//6373int b SlotHash.getSlot(B);//10374int w SlotHash.getSlot(W);//10770int end SlotHash.getSlot(艾弗森大苏打的幅度萨芬热微软微软微软464666sswwwvvvbbssssss);//5161System.out.println(a);System.out.println(b);System.out.println(w);System.out.println(end);}// // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) //package io.lettuce.core.cluster;import io.lettuce.core.codec.CRC16; import io.lettuce.core.codec.RedisCodec; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map;public class SlotHash {public static final byte SUBKEY_START 123;public static final byte SUBKEY_END 125;public static final int SLOT_COUNT 16384;private SlotHash() {}public static final int getSlot(String key) {return getSlot(key.getBytes());}public static int getSlot(byte[] key) {return getSlot(ByteBuffer.wrap(key));}public static int getSlot(ByteBuffer key) {int limit key.limit();int position key.position();int start indexOf(key, (byte)123);int end;if (start ! -1) {end indexOf(key, start 1, (byte)125);if (end ! -1 end ! start 1) {key.position(start 1).limit(end);}}try {if (key.hasArray()) {end CRC16.crc16(key.array(), key.position(), key.limit() - key.position()) % 16384;return end;}end CRC16.crc16(key) % 16384;} finally {key.position(position).limit(limit);}return end;}private static int indexOf(ByteBuffer haystack, byte needle) {return indexOf(haystack, haystack.position(), needle);}private static int indexOf(ByteBuffer haystack, int start, byte needle) {for(int i start; i haystack.remaining(); i) {if (haystack.get(i) needle) {return i;}}return -1;}static K, V MapInteger, ListK partition(RedisCodecK, V codec, IterableK keys) {MapInteger, ListK partitioned new HashMap();Iterator var3 keys.iterator();while(var3.hasNext()) {K key var3.next();int slot getSlot(codec.encodeKey(key));if (!partitioned.containsKey(slot)) {partitioned.put(slot, new ArrayList());}CollectionK list (Collection)partitioned.get(slot);list.add(key);}return partitioned;}static K MapK, Integer getSlots(MapInteger, ? extends IterableK partitioned) {MapK, Integer result new HashMap();Iterator var2 partitioned.entrySet().iterator();while(var2.hasNext()) {Map.EntryInteger, ? extends IterableK entry (Map.Entry)var2.next();Iterator var4 ((Iterable)entry.getValue()).iterator();while(var4.hasNext()) {K key var4.next();result.put(key, entry.getKey());}}return result;} } // // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) //package io.lettuce.core.codec;import java.nio.ByteBuffer;public class CRC16 {private static final int[] LOOKUP_TABLE new int[]{0, 4129, 8258, 12387, 16516, 20645, 24774, 28903, 33032, 37161, 41290, 45419, 49548, 53677, 57806, 61935, 4657, 528, 12915, 8786, 21173, 17044, 29431, 25302, 37689, 33560, 45947, 41818, 54205, 50076, 62463, 58334, 9314, 13379, 1056, 5121, 25830, 29895, 17572, 21637, 42346, 46411, 34088, 38153, 58862, 62927, 50604, 54669, 13907, 9842, 5649, 1584, 30423, 26358, 22165, 18100, 46939, 42874, 38681, 34616, 63455, 59390, 55197, 51132, 18628, 22757, 26758, 30887, 2112, 6241, 10242, 14371, 51660, 55789, 59790, 63919, 35144, 39273, 43274, 47403, 23285, 19156, 31415, 27286, 6769, 2640, 14899, 10770, 56317, 52188, 64447, 60318, 39801, 35672, 47931, 43802, 27814, 31879, 19684, 23749, 11298, 15363, 3168, 7233, 60846, 64911, 52716, 56781, 44330, 48395, 36200, 40265, 32407, 28342, 24277, 20212, 15891, 11826, 7761, 3696, 65439, 61374, 57309, 53244, 48923, 44858, 40793, 36728, 37256, 33193, 45514, 41451, 53516, 49453, 61774, 57711, 4224, 161, 12482, 8419, 20484, 16421, 28742, 24679, 33721, 37784, 41979, 46042, 49981, 54044, 58239, 62302, 689, 4752, 8947, 13010, 16949, 21012, 25207, 29270, 46570, 42443, 38312, 34185, 62830, 58703, 54572, 50445, 13538, 9411, 5280, 1153, 29798, 25671, 21540, 17413, 42971, 47098, 34713, 38840, 59231, 63358, 50973, 55100, 9939, 14066, 1681, 5808, 26199, 30326, 17941, 22068, 55628, 51565, 63758, 59695, 39368, 35305, 47498, 43435, 22596, 18533, 30726, 26663, 6336, 2273, 14466, 10403, 52093, 56156, 60223, 64286, 35833, 39896, 43963, 48026, 19061, 23124, 27191, 31254, 2801, 6864, 10931, 14994, 64814, 60687, 56684, 52557, 48554, 44427, 40424, 36297, 31782, 27655, 23652, 19525, 15522, 11395, 7392, 3265, 61215, 65342, 53085, 57212, 44955, 49082, 36825, 40952, 28183, 32310, 20053, 24180, 11923, 16050, 3793, 7920};private CRC16() {}public static int crc16(byte[] bytes) {return crc16(bytes, 0, bytes.length);}public static int crc16(byte[] bytes, int off, int len) {int crc 0;int end off len;for(int i off; i end; i) {crc doCrc(bytes[i], crc);}return crc \uffff;}public static int crc16(ByteBuffer bytes) {int crc;for(crc 0; bytes.hasRemaining(); crc doCrc(bytes.get(), crc)) {}return crc \uffff;}private static int doCrc(byte b, int crc) {return crc 8 ^ LOOKUP_TABLE[(crc 8 ^ b 255) 255];} } 面试题为啥是16384个槽位 1 官网规定的16384 2 CRC16算法产生hash值有16bit2^1665536,太大压缩位图较难信息传递减弱网络拥堵 集群配置三主三从 配置文件 6007、6008、6009、6012、6014、6015 6个端口服务配置分别如下 bind 0.0.0.0 daemonize yes protected-mode no port 6007 logfile cluster6007.log pidfile /redis-learn/redis-7.0.9/conf/cluster/cluster6007.pid dir /redis-learn/redis-7.0.9/conf/cluster/cluster6007 dbfilename dump6007.rdb appendonly yes appendfilename appendonly6007.aof requirepass 123456 masterauth 123456cluster-enabled yes cluster-config-file nodes-6007.conf cluster-node-timeout 5000 bind 0.0.0.0 daemonize yes protected-mode no port 6008 logfile cluster6008.log pidfile /redis-learn/redis-7.0.9/conf/cluster/cluster6008.pid dir /redis-learn/redis-7.0.9/conf/cluster/cluster6008 dbfilename dump6008.rdb appendonly yes appendfilename appendonly6008.aof requirepass 123456 masterauth 123456cluster-enabled yes cluster-config-file nodes-6008.conf cluster-node-timeout 5000 bind 0.0.0.0 daemonize yes protected-mode no port 6009 logfile cluster6009.log pidfile /redis-learn/redis-7.0.9/conf/cluster/cluster6009.pid dir /redis-learn/redis-7.0.9/conf/cluster/cluster6009 dbfilename dump6009.rdb appendonly yes appendfilename appendonly6009.aof requirepass 123456 masterauth 123456cluster-enabled yes cluster-config-file nodes-6009.conf cluster-node-timeout 5000 bind 0.0.0.0 daemonize yes protected-mode no port 6012 logfile cluster6012.log pidfile /redis-learn/redis-7.0.9/conf/cluster/cluster6012.pid dir /redis-learn/redis-7.0.9/conf/cluster/cluster6012 dbfilename dump6012.rdb appendonly yes appendfilename appendonly6012.aof requirepass 123456 masterauth 123456cluster-enabled yes cluster-config-file nodes-6012.conf cluster-node-timeout 5000 bind 0.0.0.0 daemonize yes protected-mode no port 6014 logfile cluster6014.log pidfile /redis-learn/redis-7.0.9/conf/cluster/cluster6014.pid dir /redis-learn/redis-7.0.9/conf/cluster/cluster6014 dbfilename dump6014.rdb appendonly yes appendfilename appendonly6014.aof requirepass 123456 masterauth 123456cluster-enabled yes cluster-config-file nodes-6014.conf cluster-node-timeout 5000 bind 0.0.0.0 daemonize yes protected-mode no port 6015 logfile cluster6012.log pidfile /redis-learn/redis-7.0.9/conf/cluster/cluster6015.pid dir /redis-learn/redis-7.0.9/conf/cluster/cluster6015 dbfilename dump6015.rdb appendonly yes appendfilename appendonly6015.aof requirepass 123456 masterauth 123456cluster-enabled yes cluster-config-file nodes-6015.conf cluster-node-timeout 5000 启动 ./redis-server …/conf/cluster/cluster6007.conf ./redis-server …/conf/cluster/cluster6008.conf ./redis-server …/conf/cluster/cluster6009.conf ./redis-server …/conf/cluster/cluster6010.conf ./redis-server …/conf/cluster/cluster6011.conf ./redis-server …/conf/cluster/cluster6012.conf 通过redis-cli命令为6台机器构建集群关系 #-cluster-replicas 1 表示为每个master创建一个slave节点 redis-cli -a 123456 --cluster create --cluster-replicas 1 172.16.64.21:6007 172.16.64.21:6008 172.16.64.21:6009 172.16.64.21:6012 172.16.64.21:6014 172.16.64.21:6015 连接任意一个节点查看集群状态 #-c表示集群 不加的话不是按照集群启动的对于在别的机器上的key会报错 ./redis-cli -a 123456 -p 6007 -c 查看 #查看节点信息 cluster nodes #查看集群信息 cluster info #查看当前节点主从关系 info replication 测试 新增key查看是否成功 主从容错切换迁移 找出一个主从测试即可目前6007是6015的主节点 关闭6007查看6015会不会切换成master 启动6007看6015会不会让位 Redis集群不保证强一致性意味着在特定的条件下Redis集群可能会丢掉一些被系统收到的写入请求命令因为本质还是发送心跳包需要一些时间判断是否down机如果down机对应的slave直接成为master如果想要原先的master继续做master的话 CLUSTER FAILOVER # 让谁上位 就在谁的端口号下执行这个命令 主从扩容 增加6016 6017两台服务 bind 0.0.0.0 daemonize yes protected-mode no port 6016 logfile cluster6016.log pidfile /redis-learn/redis-7.0.9/conf/cluster/cluster6016.pid dir /redis-learn/redis-7.0.9/conf/cluster/cluster6016 dbfilename dump6016.rdb appendonly yes appendfilename appendonly6016.aof requirepass 123456 masterauth 123456cluster-enabled yes cluster-config-file nodes-6016.conf cluster-node-timeout 5000 bind 0.0.0.0 daemonize yes protected-mode no port 6017 logfile cluster6017.log pidfile /redis-learn/redis-7.0.9/conf/cluster/cluster6017.pid dir /redis-learn/redis-7.0.9/conf/cluster/cluster6017 dbfilename dump6017.rdb appendonly yes appendfilename appendonly6017.aof requirepass 123456 masterauth 123456cluster-enabled yes cluster-config-file nodes-6017.conf cluster-node-timeout 5000 启动此时这两个实例都是master ./redis-server …/conf/cluster/cluster6016.conf ./redis-server …/conf/cluster/cluster6017.conf 将新增6016、6017加入原来集群中 #cluster add-node 新节点ip:port 原来节点ip:port ./redis-cli -a 123456 --cluster add-node 172.16.64.21:6016 172.16.64.21:6007 检查集群情况6016 ./redis-cli -a 123456 --cluster check 172.16.64.21:6016 给6016分派卡槽从其他的服务中均一点 ./redis-cli -a 123456 --cluster reshard 172.16.64.21:6016 上述解释 all:集群中的所有主节点都会成为源节点redis-trib从各个源节点中各取出一部分哈希槽凑够4096个然后移动到6016节点上done 要从特点的哪个节点中取出 4096 个哈希槽 再次检查集群情况 ./redis-cli -a 123456 --cluster check 172.16.64.21:6016 为主节点6016分配从节点6017 –cluster-master-id 后跟的是6016的id redis-cli -a 123456 --cluster add-node 172.16.64.21:6017 172.16.64.21:6016 --cluster-slave --cluster-master-id 6ffe226dec047ac3a2e1f1be054d1ffd91007a79 主从缩容 让6016、6017下线 #卡槽有数据不能删除需要还给集群才能删除当前6017卡槽为0 ./redis-cli -a 123456 --cluster del-node 172.16.64.21:6017 6017id号 将6016的槽号情况重新分配先全部都给6007 ./redis-cli -a 123456 --cluster reshard 172.16.64.21:6016 查看集群情况 集群删除6016 #卡槽有数据不能删除需要还给集群才能删除当前6017卡槽为0 ./redis-cli -a 123456 --cluster del-node 172.16.64.21:6016 6016id号 完整提供服务配置 springboot集成集群 lettuce和jedis区别 jedisJedis Client 是Redis 官网推荐的一个面向 Java 客户端库文件实现了对各类API进行封装调用 lettuce: Lettuce是一个Redis的Java驱动包Lettuce翻译为生菜没错就是吃的那种生菜所以它的Logo就是生菜 区别spingboot2.0后默认是用lettuce连接redis服务器jedis反复连接线程资源创建和关闭开销大线程不安全 lettuce底层使用netty很多线程连接redis值需创建一个lettuce连接可以减少线程连接开销线程安全 springboot接入redis cluster需要和哨兵一样做读写分离吗 需要现在主节点是600860096015 从节点600760126014 pom文件 ?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersionparentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.7.17/versionrelativePath/ !-- lookup parent from repository --/parentgroupIdcom.redis/groupIdartifactIdredis-cluster/artifactIdversion0.0.1-SNAPSHOT/versionnameredis-cluster/namedescriptionredis-cluster/descriptionpropertiesjava.version1.8/java.version/propertiesdependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-devtools/artifactIdscoperuntime/scopeoptionaltrue/optional/dependencydependencygroupIdcom.mysql/groupIdartifactIdmysql-connector-j/artifactIdscoperuntime/scope/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependencydependencygroupIdorg.apache.commons/groupIdartifactIdcommons-pool2/artifactId/dependency/dependenciesbuildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactIdconfigurationexcludesexcludegroupIdorg.projectlombok/groupIdartifactIdlombok/artifactId/exclude/excludes/configuration/plugin/plugins/build/project 配置文件 #连接数据源 spring.datasource.druid.usernameroot spring.datasource.druid.passwordxgm2023.. spring.datasource.druid.urljdbc:mysql://172.16.204.51:3306/redis?serverTimezoneGMT%2B8 spring.datasource.druid.driver-class-namecom.mysql.cj.jdbc.Driver spring.datasource.druid.initial-size5#redis cluster #支持集群拓扑动态感应刷新,自适应拓扑刷新是否使用所有可用的更新默认false关闭 spring.redis.lettuce.cluster.refresh.adaptivetrue #定时刷新 spring.redis.lettuce.cluster.refresh.period2000 #集群信息 spring.redis.cluster.nodes172.16.64.21:6007,172.16.64.21:6008,172.16.64.21:6009,172.16.64.21:6012,172.16.64.21:6014,172.16.64.21:6015 spring.redis.password123456 spring.redis.timeout60 #默认的lettuce lettuce线程安全Jedis是同步的不支持异步Jedis客户端实例不是线程安全的需要每个线程一个Jedis实例所以一般通过连接池来使用Jedis. # 连接池最大连接数使用负值表示没有限制 spring.redis.lettuce.pool.max-active50 # 连接池中的最大空闲连接 spring.redis.lettuce.pool.max-idle50 # 连接池最大阻塞等待时间使用负值表示没有限制 spring.redis.lettuce.pool.max-wait1000 # 连接池中的最小空闲连接 spring.redis.lettuce.pool.min-idle5 spring.redis.lettuce.shutdown-timeout1000 #eviction线程调度时间间隔 spring.redis.lettuce.pool.time-between-eviction-runs2000 #最大的要重定向的次数由于集群中数据存储在多个节点所以在访问数据时需要通过节点进行转发 spring.redis.cluster.max-redirects3 #最大的连接重试次数 spring.redis.cluster.max-attempts3#日志 logging.pattern.console%date{yyyy-MM-dd HH:mm:ss.SSS} | %highlight(%5level) [%green(%16.16thread)] %clr(%-50.50logger{49}){cyan} %4line -| %highlight(%msg%n) logging.level.rootinfo logging.level.io.lettuce.coredebug logging.level.org.springframework.data.redisdebug配置类 package com.redis.redissentinel.conf; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import io.lettuce.core.ReadFrom; import io.lettuce.core.TimeoutOptions; import io.lettuce.core.cluster.ClusterClientOptions; import io.lettuce.core.cluster.ClusterTopologyRefreshOptions; import lombok.extern.slf4j.Slf4j; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.data.redis.RedisProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.*; import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import java.text.SimpleDateFormat; import java.time.Duration; import java.util.*;import org.springframework.data.redis.core.RedisTemplate;import javax.lang.model.element.NestingKind;/*** author ygr* date 2022-02-15 16:30*/ Slf4j Configuration public class RedisConfig {Value(${spring.redis.lettuce.pool.max-idle})String maxIdle;Value(${spring.redis.lettuce.pool.min-idle})String minIdle;Value(${spring.redis.lettuce.pool.max-active})String maxActive;Value(${spring.redis.lettuce.pool.max-wait})String maxWait;Value(${spring.redis.lettuce.pool.time-between-eviction-runs})String timeBetweenEvictionRunsMillis;Value(${spring.redis.cluster.nodes})String clusterNodes;Value(${spring.redis.password})String password;Value(${spring.redis.cluster.max-redirects})String maxRedirects;Value(${spring.redis.lettuce.cluster.refresh.period})String period;Value(${spring.redis.timeout})String timeout;Beanpublic LettuceConnectionFactory lettuceConnectionFactory() {GenericObjectPoolConfig genericObjectPoolConfig new GenericObjectPoolConfig();genericObjectPoolConfig.setMaxIdle(Integer.parseInt(maxIdle));genericObjectPoolConfig.setMinIdle(Integer.parseInt(minIdle));genericObjectPoolConfig.setMaxTotal(Integer.parseInt(maxActive));genericObjectPoolConfig.setMaxWait(Duration.ofMillis(Long.parseLong(maxWait)));genericObjectPoolConfig.setTimeBetweenEvictionRuns(Duration.ofMillis(Long.parseLong(timeBetweenEvictionRunsMillis)));String[] nodes clusterNodes.split(,);ListRedisNode listNodes new ArrayList();for (String node : nodes) {String[] ipAndPort node.split(:);RedisNode redisNode new RedisNode(ipAndPort[0], Integer.parseInt(ipAndPort[1]));listNodes.add(redisNode);}RedisClusterConfiguration redisClusterConfiguration new RedisClusterConfiguration();redisClusterConfiguration.setClusterNodes(listNodes);redisClusterConfiguration.setPassword(password);redisClusterConfiguration.setMaxRedirects(Integer.parseInt(maxRedirects));// 配置集群自动刷新拓扑ClusterTopologyRefreshOptions topologyRefreshOptions ClusterTopologyRefreshOptions.builder().enablePeriodicRefresh(Duration.ofSeconds(Long.parseLong(period))) //按照周期刷新拓扑.enableAllAdaptiveRefreshTriggers() //根据事件刷新拓扑.build();ClusterClientOptions clusterClientOptions ClusterClientOptions.builder()//redis命令超时时间,超时后才会使用新的拓扑信息重新建立连接.timeoutOptions(TimeoutOptions.enabled(Duration.ofSeconds(Long.parseLong(period)))).topologyRefreshOptions(topologyRefreshOptions).build();LettuceClientConfiguration clientConfig LettucePoolingClientConfiguration.builder().commandTimeout(Duration.ofSeconds(Long.parseLong(timeout))).poolConfig(genericObjectPoolConfig).readFrom(ReadFrom.REPLICA_PREFERRED) // 优先从副本读取.clientOptions(clusterClientOptions).build();LettuceConnectionFactory factory new LettuceConnectionFactory(redisClusterConfiguration, clientConfig);return factory;}public ObjectMapper objectMapper() {ObjectMapper objectMapper new ObjectMapper();objectMapper.setTimeZone(TimeZone.getTimeZone(GMT8));objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);objectMapper.setDateFormat(new SimpleDateFormat(yyyy-MM-dd HH:mm:ss));objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);return objectMapper;}BeanConditionalOnMissingBeanpublic RedisTemplateString, Object redisTemplate(LettuceConnectionFactory factory) {factory.setShareNativeConnection(false);LettuceClientConfiguration clientConfiguration factory.getClientConfiguration();// 创建RedisTemplateString, Object对象RedisTemplateString, Object template new RedisTemplate();template.setConnectionFactory(factory);// 定义Jackson2JsonRedisSerializer序列化对象Jackson2JsonRedisSerializerObject jackson2JsonRedisSerializer new Jackson2JsonRedisSerializer(Object.class);jackson2JsonRedisSerializer.setObjectMapper(objectMapper());StringRedisSerializer stringSerial new StringRedisSerializer();// redis key 序列化方式使用stringSerialtemplate.setKeySerializer(stringSerial);// redis value 序列化方式使用jacksontemplate.setValueSerializer(jackson2JsonRedisSerializer);// redis hash key 序列化方式使用stringSerialtemplate.setHashKeySerializer(stringSerial);// redis hash value 序列化方式使用jacksontemplate.setHashValueSerializer(jackson2JsonRedisSerializer);template.afterPropertiesSet();return template;}}//---------------------------------推荐下面此方式-------------------------------------------------//package com.redis.redissentinel.conf; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import io.lettuce.core.ReadFrom; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.data.redis.RedisProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisPassword; import org.springframework.data.redis.connection.RedisSentinelConfiguration; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.HashSet; import java.util.TimeZone; import org.springframework.data.redis.core.RedisTemplate; /*** author ygr* date 2022-02-15 16:30*/ Slf4j Configuration public class RedisConfig {public ObjectMapper objectMapper() {ObjectMapper objectMapper new ObjectMapper();objectMapper.setTimeZone(TimeZone.getTimeZone(GMT8));objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);objectMapper.setDateFormat(new SimpleDateFormat(yyyy-MM-dd HH:mm:ss));objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);return objectMapper;}BeanConditionalOnMissingBeanpublic RedisTemplateString, Object redisTemplate(RedisConnectionFactory factory) {// 创建RedisTemplateString, Object对象RedisTemplateString, Object template new RedisTemplate();template.setConnectionFactory(factory);// 定义Jackson2JsonRedisSerializer序列化对象Jackson2JsonRedisSerializerObject jackson2JsonRedisSerializer new Jackson2JsonRedisSerializer(Object.class);jackson2JsonRedisSerializer.setObjectMapper(objectMapper());StringRedisSerializer stringSerial new StringRedisSerializer();// redis key 序列化方式使用stringSerialtemplate.setKeySerializer(stringSerial);// redis value 序列化方式使用jacksontemplate.setValueSerializer(jackson2JsonRedisSerializer);// redis hash key 序列化方式使用stringSerialtemplate.setHashKeySerializer(stringSerial);// redis hash value 序列化方式使用jacksontemplate.setHashValueSerializer(jackson2JsonRedisSerializer);template.afterPropertiesSet();return template;}Beanpublic RedisConnectionFactory lettuceConnectionFactory(RedisProperties redisProperties) {RedisSentinelConfiguration sentinelConfig new RedisSentinelConfiguration().master(redisProperties.getSentinel().getMaster());redisProperties.getSentinel().getNodes().forEach(s - {String[] arr s.split(:);sentinelConfig.sentinel(arr[0],Integer.parseInt(arr[1]));});LettucePoolingClientConfiguration lettuceClientConfiguration LettucePoolingClientConfiguration.builder()// 读写分离若主节点能抗住读写并发则不需要设置全都走主节点即可//ANY 从任何节点读取,NEAREST 从最近节点读取,MASTER_PREFERRED / UPSTREAM_PREFERRED优先读取主节点如果主节点不可用则读取从节点,MASTER / UPSTREAM仅读取主节点.readFrom(ReadFrom.ANY_REPLICA).build();sentinelConfig.setPassword(RedisPassword.of(redisProperties.getPassword()));sentinelConfig.setDatabase(redisProperties.getDatabase());return new LettuceConnectionFactory(sentinelConfig, lettuceClientConfiguration);}}测试 package com.redis.redissentinel;import lombok.extern.slf4j.Slf4j; 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.RedisTemplate;import javax.annotation.Resource; import java.util.concurrent.TimeUnit;Slf4j SpringBootTest class RedisSentinelApplicationTests {Resourceprivate RedisTemplateString, Object redisTemplate;Testvoid witeTest() {for (int i 0; i 3; i) {try {redisTemplate.opsForValue().set(k i, v i);log.info(set value success: {}, i);Object val redisTemplate.opsForValue().get(k i);log.info(get value success: {}, val);TimeUnit.SECONDS.sleep(1);} catch (Exception e) {log.error(error: {}, e.getMessage());}}log.info(finished...);}Testvoid readTest() {Object k1 redisTemplate.opsForValue().get(k1);log.info(读取节点k1的值{},k1);}} 当前集群节点信息
http://www.dnsts.com.cn/news/33677.html

相关文章:

  • 网站备案域名所有人卡板技术支持 东莞网站建设
  • 济南网站备案程序做电商排名网站
  • 王野天 葛优做谷歌seo要发大量文章吗
  • 手机网站开发有前途求网址直接能看的2021
  • 邯郸网站建设怎么做网页设计作业致谢
  • 哪个网站做网上旅社预定泉州模板建站源码
  • 科技公司网站开发室内设计学校排行榜
  • 电影网站盗链怎么做网易企业邮箱服务器设置
  • 商业摄影网站源码网站开发支付超时如何解决
  • 网站建设平台安全问题有哪些方面大连网站制作团队
  • 建站行业如何快速成第一单wordpress+漂亮的博客
  • 号号网站开发大连网站建设网站
  • 建设银行东四十条支行支行网站wordpress白天黑夜切换
  • 做徽章标牌的企业网站html5教程零基础
  • 网站建设寻求网站怎么做网络推广
  • 免费的作文网站秦皇岛网站制作源码
  • 河南省建设注册中心网站橙色网站后台模板
  • 做网站高亮不良网站进入窗口免费正能量
  • 瑞安企业做网站新手如何做好网络营销推广
  • 4399自己做游戏网站网站内容策划书
  • 织梦网站专题模板下载网络推广方案例子
  • 网站建设作业网站建设 招聘需求
  • 网站使用网络图片做素材 侵权开发一个区块链app多少钱
  • 个人网站的设计嵌入式软件开发工具有哪些
  • 昆明云南微网站制作海口企业网站开发
  • 网站两边广告代码柳江企业网站开发公司
  • 网站开发公司前置审批网站制作周期
  • 九宫格网站模板做多肽的都有哪些网站
  • 企业网站策划qq企业邮箱怎么申请
  • 商标注册查询官方网站wordpress能不买服务器