Jedis cluster命令执行流程剖析

Lettuce vs Jedis:Redis Cluster集群连接稳定性对比与选型建议 本文深入对比了Lettuce和Jedis在Redis Cluster集群环境下的连接稳定性表现,重点分析了两者在拓扑结构感知、异常处理和连接池管理等方面的技术差异。通过实测数据和配置示例,为不同业务场景提供选型建议,帮助开发者优化Redis集群连接方案。 阅读详情

在Redis Cluster集群模式下,由于key分布在各个节点上,会造成无法直接实现mget、sInter等功能。因此,无论我们使用什么客户端来操作Redis,都要考虑单一key命令操作、批量key命令操作和多节点命令操作的情况,以及效率问题。

在之前的文章中剖析了Jedis cluster集群初始化源码,分析了源码之后可以得知,在Jedis中,使用的是JedisClusterConnection集群连接类来与Redis集群节点进行命令交互,它使用装饰模式对JedisCluster命令执行类进行了一层包装,同时对这三种不同类型的命令操作做了分类处理。

下面就看下JedisClusterConnection类中,如何实现这三种类型的key命令操作。在这里只列举一些典型的命令进行说明。本文基于spring-data-redis-1.8.4-RELEASE.jar和jedis-2.9.0.jar进行源码剖析,Redis版本为Redis 3.2.8。

单一key命令操作

对于单一命令操作,常用的就是get、set了。在JedisClusterConnection类中,get方法的实现如下:

public byte[] get(byte[] key) {
	try {
		return cluster.get(key);
	} catch (Exception ex) {
		throw convertJedisAccessException(ex);
	}
}

在上面代码中,执行cluster.get()方法时,实际上调用的是BinaryJedisCluster类的get()方法:

  public byte[] get(final byte[] key) {
    return new JedisClusterCommand<byte[]>(connectionHandler, maxAttempts) {
      @Override
      public byte[] execute(Jedis connection) {
        return connection.get(key);
      }
    }.runBinary(key);
  }

BinaryJedisCluster类的get()方法的核心操作是由JedisClusterCommand类runBinary()方法完成的,下面剖析一下该类的核心代码:

public abstract class JedisClusterCommand<T> {

	// 集群节点连接器
	private JedisClusterConnectionHandler connectionHandler;
	// 重试次数,默认5次
	private int maxAttempts;

	// 模板回调方法,执行相关的redis命令
	public abstract T execute(Jedis connection);

   public T runBinary(byte[] key) {
	    if (key == null) {
	      throw new JedisClusterException("No way to dispatch this command to Redis Cluster.");
	    }
		
	    return runWithRetries(key, this.maxAttempts, false, false);
  	}

	/**
	 * 利用重试机制运行键命令
	 * 
	 * @param key
	 *            要操作的键
	 * @param attempts
	 *            重试次数,每重试一次减1
	 * @param tryRandomNode
	 *            标识是否随机获取活跃节点连接,true为是,false为否
	 * @param asking
	 * @return
	 */
	private T runWithRetries(byte[] key, int attempts, boolean tryRandomNode, boolean asking) {
		if (attempts <= 0) {
			throw new JedisClusterMaxRedirectionsException("Too many Cluster redirections?");
		}

		Jedis connection = null;
		try {

			if (asking) {
				// TODO: Pipeline asking with the original command to make it
				// faster....
				connection = askConnection.get();
				connection.asking();

				// if asking success, reset asking flag
				asking = false;
			} else {
				if (tryRandomNode) {
					// 随机获取活跃节点连接
					connection = connectionHandler.getConnection();
				} else {
					// 计算key的slot值,然后根据slot缓存获取节点连接
					connection = connectionHandler.getConnectionFromSlot(JedisClusterCRC16.getSlot(key));
				}
			}

			// 调用具体的模板方法实现执行命令
			return execute(connection);

			// 集群节点不可达,直接抛出异常
		} catch (JedisNoReachableClusterNodeException jnrcne) {
			throw jnrcne;
		} catch (JedisConnectionException jce) {
			// 在递归执行runWithRetries方法之前释放连接
			releaseConnection(connection);
			connection = null;

			// 如果节点不能连接,重新初始化slot缓存
			if (attempts <= 1) {
				this.connectionHandler.renewSlotCache();

				throw jce;
			}

			// 出现连接错误重试执行命令
			return runWithRetries(key, attempts - 1, tryRandomNode, asking);
		} catch (JedisRedirectionException jre) {
			// 如果出现MOVE重定向错误,在连接上执行cluster slots命令重新初始化slot缓存
			if (jre instanceof JedisMovedDataException) {
				this.connectionHandler.renewSlotCache(connection);
			}

			// 在递归执行runWithRetries方法或者重建slot缓存之前释放连接,从而避免在错误的连接上执行命令,也为了避免连接泄露问题
			releaseConnection(connection);
			connection = null;

			if (jre instanceof JedisAskDataException) {
				asking = true;
				askConnection.set(this.connectionHandler.getConnectionFromNode(jre.getTargetNode()));
			} else if (jre instanceof JedisMovedDataException) {
			} else {
				throw new JedisClusterException(jre);
			}
			// slot初始化后重试执行命令
			return runWithRetries(key, attempts - 1, false, asking);
		} finally {
			//释放连接
			releaseConnection(connection);
		}
	}
}

单一key命令执行流程:

  1. 计算slot并根据slots缓存获取目标节点连接,发送命令
  2. 如果出现连接错误,使用重试机制执行键命令,每次命令重试对 attempts参数减1
  3. 捕获到MOVED重定向错误,使用cluster slots命令更新slots 缓存(renewSlotCache方法)
  4. 重复执行1 ~ 3步,直到命令执行成功,或者当attempts <= 0时抛出JedisClusterMaxRedirectionsException异常
  5. 在递归执行runWithRetries方法或者重建slot缓存之前释放连接,从而避免在错误的连接上执行命令,也为了避免连接泄露问题

多节点命令操作

在Redis Cluster中,有些命令如keys、flushall和删除指定模式的键这些操作,需要遍历所有的节点才可以完成。下面就以keys命令来说明这种情况下JedisClusterConnection类是如何完成该操作的,该类中keys()方法代码如下:

public Set<byte[]> keys(final byte[] pattern) {

		Assert.notNull(pattern, "Pattern must not be null!");

		//在所有主节点上执行keys命令,然后返回一个Collection集合
		Collection<Set<byte[]>> keysPerNode = clusterCommandExecutor
				.executeCommandOnAllNodes(new JedisClusterCommandCallback<Set<byte[]>>() {

					@Override
					public Set<byte[]> doInCluster(Jedis client) {
						return client.keys(pattern);
					}
				}).resultsAsList();

		//遍历执行keys命令获得的结果,然后添加进Set集合返回
		Set<byte[]> keys = new HashSet<byte[]>();
		for (Set<byte[]> keySet : keysPerNode) {
			keys.addAll(keySet);
		}
		return keys;
	}

在上面代码中我们看到了keys()方法内部调用了ClusterCommandExecutor类的executeCommandOnAllNodes()方法,该类是一个集群命令执行类,它提供了在多个集群节点上批量执行命令的特性,由于考虑到在多个节点上执行命令的效率问题,它使用Spring的org.springframework.core.task包里面的AsyncTaskExecutor接口来为命令执行操作提供异步支持,然后返回异步执行结果。ClusterCommandExecutor类的executeCommandOnAllNodes()方法及关联方法实现剖析如下:

      /**
	 * 使用ClusterCommandCallback接口实现类的doInCluster()方法在所有可达的主节点上执行命令
	 *
	 * @param cmd
	 * @return
	 * @throws ClusterCommandExecutionFailureException
	 */
	public <S, T> MulitNodeResult<T> executeCommandOnAllNodes(final ClusterCommandCallback<S, T> cmd) {
		// getClusterTopology().getActiveMasterNodes()获取的是所有的主节点
		return executeCommandAsyncOnNodes(cmd, getClusterTopology().getActiveMasterNodes());
	}
	
	/**
	 * @param callback
	 * @param nodes
	 * @return
	 * @throws ClusterCommandExecutionFailureException
	 * @throws IllegalArgumentException
	 *             in case the node could not be resolved to a topology-known node
	 */
	public <S, T> MulitNodeResult<T> executeCommandAsyncOnNodes(final ClusterCommandCallback<S, T> callback, Iterable<RedisClusterNode> nodes) {

		Assert.notNull(callback, "Callback must not be null!");
		Assert.notNull(nodes, "Nodes must not be null!");

		List<RedisClusterNode> resolvedRedisClusterNodes = new ArrayList<RedisClusterNode>();
		ClusterTopology topology = topologyProvider.getTopology();

		// 遍历Redis集群节点集合nodes,获取节点信息
		for (final RedisClusterNode node : nodes) {
			try {
				resolvedRedisClusterNodes.add(topology.lookup(node));
			} catch (ClusterStateFailureException e) {
				throw new IllegalArgumentException(String.format("Node %s is unknown to cluster", node), e);
			}
		}

		// 遍历节点信息,在相应Redis集群节点上执行相关命令
		Map<NodeExecution, Future<NodeResult<T>>> futures = new LinkedHashMap<NodeExecution, Future<NodeResult<T>>>();
		for (final RedisClusterNode node : resolvedRedisClusterNodes) {

			futures.put(new NodeExecution(node), executor.submit(new Callable<NodeResult<T>>() {

				@Override
				public NodeResult<T> call() throws Exception {
					return executeCommandOnSingleNode(callback, node);
				}
			}));
		}

		// 解析执行结果并返回
		return collectResults(futures);
	}
	
	public <S, T> NodeResult<T> executeCommandOnSingleNode(ClusterCommandCallback<S, T> cmd, RedisClusterNode node) {
		return executeCommandOnSingleNode(cmd, node, 0);
	}

	private <S, T> NodeResult<T> executeCommandOnSingleNode(ClusterCommandCallback<S, T> cmd, RedisClusterNode node, int redirectCount) {

		Assert.notNull(cmd, "ClusterCommandCallback must not be null!");
		Assert.notNull(node, "RedisClusterNode must not be null!");

		if (redirectCount > maxRedirects) {
			throw new TooManyClusterRedirectionsException(String.format(
					"Cannot follow Cluster Redirects over more than %s legs. Please consider increasing the number of redirects to follow. Current value is: %s.",
					redirectCount, maxRedirects));
		}

		RedisClusterNode nodeToUse = lookupNode(node);

		S client = this.resourceProvider.getResourceForSpecificNode(nodeToUse);
		Assert.notNull(client, "Could not acquire resource for node. Is your cluster info up to date?");

		try {
			// 在相应Redis节点上执行命令,具体执行命令的函数是实现ClusterCommandCallback接口的类的doInCluster方法
			return new NodeResult<T>(node, cmd.doInCluster(client));
		} catch (RuntimeException ex) {

			RuntimeException translatedException = convertToDataAccessExeption(ex);
			// 如果请求不被目标服务器接受,则进行重试,重新执行命令:redirectCount + 1
			if (translatedException instanceof ClusterRedirectException) {
				ClusterRedirectException cre = (ClusterRedirectException) translatedException;
				return executeCommandOnSingleNode(cmd, topologyProvider.getTopology().lookup(cre.getTargetHost(), cre.getTargetPort()),
						redirectCount + 1);
			} else {
				throw translatedException != null ? translatedException : ex;
			}
		} finally {
			this.resourceProvider.returnResourceForSpecificNode(nodeToUse, client);
		}
	}

多节点命令执行流程:

  1. 使用 getClusterTopology().getActiveMasterNodes()方法获取所有的可达的主节点。这里的可达表示主节点可以被连接上且状态不为fail状态
  2. 遍历所有主节点,然后在这些节点上异步执行相应的命令,最后将结果作为一个集合返回
  3. 如果请求不被目标服务器接受,则进行重试,重新执行命令,每次对redirectCount + 1,但redirectCount的次数不能大于maxRedirects最大重试次数,大于后会抛出TooManyClusterRedirectionsException异常

批量key命令操作

与keys、flushall等多节点命令相似,mget等批量key操作命令也要遍历多个节点执行相关命令。下面就以mget命令来说明这种情况下JedisClusterConnection类是如何完成该操作的,该类中mGet()方法代码如下:

public List<byte[]> mGet(byte[]... keys) {

		Assert.noNullElements(keys, "Keys must not contain null elements!");

		// 如果进行批量操作的key的slot值相同,表示key都在同一节点上,则直接在key所在的节点执行命令
		if (ClusterSlotHashUtil.isSameSlotForAllKeys(keys)) {
			return cluster.mget(keys);
		}

		// 如果进行批量操作的key的slot值不同,表示key不在同一节点上,则需要计算key的slot值,根据slot确定key所在的节点,然后执行命令
		return this.clusterCommandExecutor.executeMuliKeyCommand(new JedisMultiKeyClusterCommandCallback<byte[]>() {

			@Override
			public byte[] doInCluster(Jedis client, byte[] key) {
				return client.get(key);
			}
		}, Arrays.asList(keys)).resultsAsListSortBy(keys);
	}

类似地,在上面代码中我们看到了mGet()方法内部调用了ClusterCommandExecutor类的executeMuliKeyCommand()方法。该方法实现剖析如下:

      /**
	 * 在一组Redis集群节点上进行一个或多个key操作
	 *
	 * @param cmd
	 * @return
	 * @throws ClusterCommandExecutionFailureException
	 */
	public <S, T> MulitNodeResult<T> executeMuliKeyCommand(final MultiKeyClusterCommandCallback<S, T> cmd, Iterable<byte[]> keys) {

		// 节点和key映射Map,一个节点上有多个key
		Map<RedisClusterNode, Set<byte[]>> nodeKeyMap = new HashMap<RedisClusterNode, Set<byte[]>>();

		// 遍历key集合,将key添加到相应的Redis集群节点集合中
		for (byte[] key : keys) {
			// 通过getClusterTopology().getKeyServingNodes(key)方法计算key的slot值,然后获取key所在的Redis集群节点信息
			for (RedisClusterNode node : getClusterTopology().getKeyServingNodes(key)) {

				if (nodeKeyMap.containsKey(node)) {
					nodeKeyMap.get(node).add(key);
				} else {
					Set<byte[]> keySet = new LinkedHashSet<byte[]>();
					keySet.add(key);
					nodeKeyMap.put(node, keySet);
				}
			}
		}

		Map<NodeExecution, Future<NodeResult<T>>> futures = new LinkedHashMap<NodeExecution, Future<NodeResult<T>>>();

		// 遍历nodeKeyMap,如果是节点是主节点,则执行相关key的命令操作
		for (final Entry<RedisClusterNode, Set<byte[]>> entry : nodeKeyMap.entrySet()) {

			if (entry.getKey().isMaster()) {
				for (final byte[] key : entry.getValue()) {
					futures.put(new NodeExecution(entry.getKey(), key), executor.submit(new Callable<NodeResult<T>>() {

						@Override
						public NodeResult<T> call() throws Exception {
							return executeMultiKeyCommandOnSingleNode(cmd, entry.getKey(), key);
						}
					}));
				}
			}
		}

		return collectResults(futures);
	}

批量key命令执行流程:

  1. 先使用ClusterSlotHashUtil.isSameSlotForAllKeys()方法计算出这些key的slot值,接下来判断如果进行批量操作的key的slot值相同,表示key都在同一节点上,则直接在key所在的节点执行命令。否则,执行第2步
  2. 如果进行批量操作的key的slot值不同,表示key不在同一节点上,则需要计算key的slot值,根据slot确定key所在的节点,然后在该节点上执行命令,最后封装结果到集合里面返回

总结

  1. 无论是哪种类型的key操作,都是在Redis集群的主节点上执行命令的。这跟Redis Cluster集群的特性有关,Redis一般不允许在从节点上进行读写操作,在JedisClusterInfoCache类中,slots这个Map本地缓存保存的也是slot槽和主节点的连接池信息
  2. 对于keys等多节点命令来说,不需要计算key的slot值,只需要遍历全部主节点然后执行命令即可
  3. 对于单一key和批量key命令操作来说,需要计算key的slot值,根据slot确定key所在的节点,然后在该节点上执行命令
  4. Redis使用单线程模式执行命令,每一次命令执行需要经过发送命令、执行命令、返回结果三个阶段。在集群条件下,不同节点执行命令的效率是不同的,对于多节点命令和批量key命令操作,考虑到命令执行时间过长,可能导致其它命令阻塞的情况,客户端需要在命令执行时提供异步支持
Jedis cluster 源码解读 1、底层结构分析 我们从JedisCluster类入手 public class JedisCluster extends BinaryJedisCluster implements JedisCommands, MultiKeyJedisClusterCommands, JedisClusterScriptingCommands 这个类继承了BinaryJedisCluster,实现了... 阅读详情

相关推荐

车载测试面试题总结

首先确认是什么问题,如果是测试软件的问题就先确定自己的测试方法有没有问题,如果没有问题,那就是测试软件的问题,这时候就需要提bug 进行跟踪,(比如BCM测试的时候,先明确测试的输入,对输入)进行需求分析,然后设计测试用例,进行用例评审,评审完执行测试用例形成最终的版本,台架分为:hil(黑尔)台架,单个控制器的台架、整车台架、车身台架、动力系统台架等,主要验证其功能,或者实车无法满足的测试环境。这个人不可能一直,点击几千次或者多少次几个小时连续点击,人不可能一直在点。因为要模拟一下这个稳定性,

woaxiaoqing的博客 7813

SpringBoot整合Redis问题

#####ClusterHostAndPorts must not be null(错误消息) 原因:没有配置好集群 解决方案:在配置文件里加上spring.redis.cluster.nodes即可 比如spring.redis.cluster.nodes=192.168.130.83:8379,192.168.130.83:6380 ...

embbls的博客 1278

华三模拟器实战:3分钟搞定路由器DHCP地址池配置(附常见错误排查)

本文提供华三模拟器中路由器DHCP地址池的实战配置指南。通过分步详解,帮助用户在3分钟内完成基础设置,并深入讲解多地址池、中继配置等进阶应用。文章重点剖析了DHCP服务无法工作的常见原因,提供从客户端到服务器的系统性排错方法,助力快速定位并解决地址分配失败、获取参数错误等典型问题。

w1x2y3的博客 360

Jedis cluster集群初始化源码剖析

环境 jar版本:spring-data-redis-1.8.4-RELEASE.jar、jedis-2.9.0.jar 测试环境:Redis 3.2.8,八个集群节点 applicationContext-redis-cluster.xml 配置文件: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="htt...

八荒六合唯我独尊 987

为什么你的ESXI无法识别移动硬盘?一步步教你解决USB存储挂载问题

本文深入解析了ESXi无法识别移动硬盘的根本原因,并提供了从诊断到解决的完整方案。核心在于理解ESXi的USB Arbitrator服务机制,通过检查服务状态、内核设备识别及分区表,逐步定位问题。文章详细指导了如何禁用USB仲裁服务以在主机挂载USB存储,或将其直通给虚拟机,并针对大容量硬盘、USB 3.0兼容性等进阶问题给出了实用建议。

qq_27496129的博客 331

图像去雾新思路:手把手教你复现DEA-Net中的“细节增强卷积”与PyTorch实现

本文详细解析了DEA-Net中的'细节增强卷积'(DEConv)与PyTorch实现,通过多分支差分卷积和重参数化技术,显著提升单图像去雾效果。文章从数学原理到代码实现,手把手指导复现这一创新架构,帮助开发者在保持轻量化的同时实现41dB以上的PSNR指标,适用于自动驾驶、遥感监测等关键领域。

weixin_30323631的博客 505

(十一)Redis集群JedisCluster实现keys命令方法

由于JedisCluster集群类不支持像单机模式下的keys方法,下面的类我们就模拟keys命令方法: 一、获取集群类   package redis.v1.client.server; import java.util.ArrayList; import java.util.Date; import java.util.HashSet; import java.util.Iterat...

OceanSky的专栏 4316

基于STM32L4XX、HAL库的Ra-01SC-P LoRa模块驱动程序设计

0x22) { // SX1276/SX1278版本号。// 发射功率(2-20)// 工作频率(Hz)// 编码率(5-8)

zhusl6688的博客 423

第四章阅读 jedis 源码之 JedisCluster 类

JedisCluster 是 jedis 连接 redis 集群操作的一个类,封装了很多操作方法和具体的类,我们先来看 JedisCluster 体系关系图: 其实从这里就可以看出整个体系结构根据是否为二进制分为两类。BinaryJedisCluster 实现了集群的二进制操作,而JedisCluster 直接继承了 BinaryJedisCluster 方法,实现了各种封装类型的方法操作。 下面我们先看下 JedisCluster 构造方法: public JedisCluster(H..

tobeng的博客 1532

003、高通骁龙Spectra ISP架构深度解析:IFE/BPS/IPE流水线与Chromatix调优实战

摘要: 本文深入解析高通骁龙Spectra ISP架构,重点剖析IFE、BPS、IPE三阶段的流水线协作机制与Chromatix调优实战。通过夜景预览"水波纹"案例,揭示HDR对齐与TNR运动估计的关联性问题,指出ISP调优需关注模块间的时序与带宽约束。文章详解各模块核心功能:IFE负责RAW域处理(HDR合成/校正),BPS专注降噪与细节增强,IPE进行YUV域精处理。针对Chromatix调优,强调参数与寄存器映射关系,并给出LSC网格密度、TNR运动灵敏度、LTM光晕等典型问题的解决方案。最后提出实用

zzfmlxs的博客 228

上下双相机定位贴合(原理到应用,halcon源码详解)

上下双相机定位贴合(原理到应用,halcon源码详解) 一、简介(类型与之前的文章)看你们理解那个文章快 主要讲解上下双相机定位贴合的原理和实现过程,包括各种标定、组合使用及具体的halcon源码实现,适用于的X、Y、Z三轴加一旋转轴系统,如模组组成的多轴系统、Scara四轴机器、六轴机器人(在运行过程中保证几个自由度不动,运行即可) 二、标定介绍 这一小节总结了通用的相机和轴的相对位置模型,并对其标定进行详细讲解 本系统仅使用了九点标定,精度可做到0.05mm 九点标定作用: A、本质就是仿射变换,一个坐

苏州程序大白的博客 9973

Redis_Jedis, JedisCluster 扩展 keys 方法实现

  最近,我们使用 Java 操作 Redis 比较多,用的组件是 Jedis ,下面是一个 maven 坐标。 &lt;dependency&gt; &lt;groupId&gt;redis.clients&lt;/groupId&gt; &lt;artifactId&gt;jedis&lt;/artifactId&gt; &lt;version&gt;2.9.0&...

迎难而上 4626

(ICLR 2025)【源码讲解+复现】TIMER-XL: Long-Context Transformers for Unified Time Series Forecasting

本文提出了一种统一的多变量时序预测模型Timer-XL,其核心创新包括:1)采用自回归解码器架构,将多变量时序预测统一为next-token预测问题;2)设计TimeAttention机制,通过相对位置编码和因果掩码捕获时序位置和变量间交互;3)支持长上下文预训练以提升零样本迁移能力。模型架构包含嵌入层、时间感知注意力块和预测头,采用MSE损失进行端到端训练。实验表明该方法在多种时序任务上表现优异,特别是在长跨度预测和少样本场景下。代码实现提供了完整的模型定义、数据加载和训练流程,支持自定义配置参数。

1145

全面剖析Redis Cluster原理和应用

全面剖析Redis Cluster原理和应用1.Redis Cluster总览1.1 设计原则和初衷在官方文档Cluster Spec中,作者详细介绍了Redis集群为什么要设计成现在的样子。最核心的目标有三个: 性能:这是Redis赖以生存的看家本领,增加集群功能后当然不能对性能产生太大影响,所以Redis采取了P2P而非Proxy方式、异步复制、客户端重定向等设计,而牺牲了部分的一致性、使用性。

西代零零发 10万+

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Jedis集群管理:深入解析槽位信息的获取与动态更新机制

​。

u014200244的专栏 716

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

Redis100篇 - Redis Cluster vs Codis 集群方案选型建议

Redis Cluster与Codis选型对比指南 本文从架构原理、部署运维、客户端支持等维度对比Redis Cluster和Codis两种集群方案。Redis Cluster采用去中心化架构,基于Gossip协议和Slot分片,适合追求简单标准的场景;Codis基于Proxy路由,客户端兼容性好但组件复杂。通过配置示例和架构图详细说明了两者的部署方式,指出Codis的运维成本更高。最后给出Java客户端集成示例,推荐Redis Cluster+Lettuce的组合方案。结论建议:新项目优先选择Redis

千淘万漉虽辛苦,吹尽狂沙始到金 2万+

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Redis之Cluster应用及源码分析

Jedis 有4 种工作模式:单节点、分片(Sharded)、哨兵(Sentinel)、集群(Cluster)。前面两篇我们分别对Sharded、Sentinel通过实际应用的例子进行了源码剖析,本文将通过实际的例子对Redis的Cluster进行源码剖析。 前两篇请参考: Redis之Sharded应用及源码分析 Redis之Sentinel应用及源码分析 1、环境: 对于Redis Clust...

qq_33996921的博客 766

redis深度剖析: 05 redis cluster核心原理

一、节点间的内部通信机制集中式的集群元数据存储和维护1、基础通信原理(1)redis cluster节点间采取gossip协议进行通信跟集中式不同,不是将集群元数据(节点信息,故障,等等)集中存储在某个节点上,而是互相之间不断通信,保持整个集群所有节点的数据是完整的维护集群的元数据用得,集中式,一种叫做gossip集中式:好处在于,元数据的更新和读取,时效性非常好,一旦元数据...

184
上一篇: Jedis cluster集群初始化源码剖析
下一篇: 常用 Git 命令清单
Viking_bird
博客等级 码龄11年 92粉丝 183原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值