codis和jedis性能比较

本文介绍了Jedis作为Redis的Java客户端实现,并通过代码示例展示了如何使用Jedis进行操作。同时,文章还介绍了Codis作为分布式Redis解决方案的优势,包括其在动态扩容方面的表现,并通过图表对比了Jedis与Codis的性能。
一. 原理:
1. Jedis是redis的java版本的客户端实现。
1.1 以下是jedis代码测试,使用了两个redis服务:


public class RedisShardPoolTest {
static ShardedJedisPool pool;//切片连接池
static{
JedisPoolConfig config =new JedisPoolConfig();//Jedis池配置
config.setMaxActive(300);//最大活动的对象个数
config.setMaxIdle(1000 * 60);//对象最大空闲时间
config.setMaxWait(1000 * 10);//获取对象时最大等待时间
config.setTestOnBorrow(true);//;如果为true,则得到的jedis实例均是可用的;
String hostA = "127.0.0.1";//服务器地址
int portA = 6379;//redis端口号
String hostB = "127.0.0.1";
int portB = 6378;
List<JedisShardInfo> jdsInfoList =new ArrayList<JedisShardInfo>(2);
JedisShardInfo infoA = new JedisShardInfo(hostA, portA);
JedisShardInfo infoB = new JedisShardInfo(hostB, portB);
jdsInfoList.add(infoA);
jdsInfoList.add(infoB);
pool =new ShardedJedisPool(config, jdsInfoList);
}
public static void main(String[] args) {
long s1=System.currentTimeMillis();
Map<String, String> map=new HashMap<String, String>();
for(int i=0; i<1000; i++){
ShardedJedis jds = null;//切片客户端连接
jds = pool.getResource();
try {
map.put("s"+i, "s"+i);
jds.hmset("s"+i, map);
} catch (Exception e) {
e.printStackTrace();
} finally {
pool.returnResource(jds);
}
}
long s2=System.currentTimeMillis();
System.out.println(testTime(s2-s1));
}
public static String testTime(long ss){
String aa=null;
long zongmiaoshu = ss / 1000;
long dangqianmiaoshu = zongmiaoshu % 60;
long zongfenshu = zongmiaoshu /60;
long dangqianfenshu = zongfenshu % 60;
long zongshishu = zongfenshu / 60;
long dangqianshishu = zongshishu % 24;
aa="当前时间:" + dangqianshishu + ":" + dangqianfenshu + ":" + dangqianmiaoshu;
return aa;
}
}


Codis 是一个分布式 Redis 解决方案,对于上层的应用来说, 连接到 Codis Proxy 和连接原生的 Redis Server 没有明显的区别 ,上层应用可以像使用单机的 Redis 一样使用, Codis 底层会处理请求的转发, 不停机的数据迁移等工作, 所有后边的一切事情, 对于前面的客户端来说是透明的, 可以简单的认为后边连接的是一个内存无限大的 Redis 服务.
下图可以看到redis客户端连接是是codis的代理。代理连接很多的分组,一个组包括一个master和0到多个slave。

[img]https://img-blog.youkuaiyun.com/20150225142523301[/img]

2.1 codis代码测试:先配置codis,codis的安装配置就不讲了,我测试在集成在spring中了。
spring中的配置:


<bean id="ehcacheService" class="net.okdi.core.common.redis.RedisServiceImpl"/>
<context:property-placeholder location="classpath:/redis.properties"
ignore-unresolvable="true" />
<bean id="jedisConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxActive" value="${redis_max_active}"></property>
<property name="maxIdle" value="${redis_max_idle}"></property>
<property name="maxWait" value="${redis_max_wait}"></property>
<property name="testOnBorrow" value="${redis_test_on_borrow}"></property>
</bean>
<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="hostName" value="${redis_addr}"></property>
<property name="port" value="${redis_port}"></property>
<property name="password" value="${redis_auth}"></property>
<property name="poolConfig" ref="jedisConfig"></property>
</bean>
<bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
<property name="connectionFactory" ref="connectionFactory" />
如果不配置Serializer,那么存储的时候智能使用String,如果用User类型存储,那么会提示错误User can't cast to String!!!
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
</property>
<property name="valueSerializer">
<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
</property>
</bean>


redis配置文件:


redis_addr=192.168.31.204
redis_port=19000 (codis代理服务器端口)
redis_auth=okdi
redis_max_active=1024
redis_max_idle=200
redis_max_wait=10000
redis_timeout=10000
redis_test_on_borrow=true


封装的redis方法,用的是redisTemplate:


public class RedisServiceImpl implements EhcacheService {

private static Logger logger = Logger.getLogger(EhcacheServiceImpl.class);

@Autowired
private StringRedisTemplate redisTemplate;
@Autowired
private RedisConstant redisConstant;

@Override
public void put(String cacheName, String key, String value) {
// boolean bool = redisTemplate.hasKey(cacheName);
if (cacheName==null || "".equals(cacheName) || key==null || "".equals(key)) {
return;
}
//放入redis
redisTemplate.opsForHash().put(cacheName, key, value);

long expireTime = redisConstant.getExpireTime(cacheName);
//如果不等于-1,则该cacheName配置有过期时间
if(expireTime != -1){
redisTemplate.expire(cacheName, expireTime, TimeUnit.SECONDS);
}
}

@Override
public void put(String cacheName, String key, Object value) {
if (cacheName==null || "".equals(cacheName) || key==null || "".equals(key)) {
return;
}
//放入redis
redisTemplate.opsForHash().put(cacheName, key, JSON.toJSONString(value));

long expireTime = redisConstant.getExpireTime(cacheName);
//如果不等于-1,则该cacheName配置有过期时间
if(expireTime != -1){
redisTemplate.expire(cacheName, expireTime, TimeUnit.SECONDS);
}
}




用junit测试:

public class test11 extends BaseTest{

@Autowired
private EhcacheService redisService;
@SuppressWarnings("rawtypes")
@Test
public void test1(){
long s1=System.currentTimeMillis();

for(int i=0;i<10000;i++){
redisService.put("a"+i, "a"+i,"a"+i);
redisService.remove("a"+i, "a"+i);
}
long s2=System.currentTimeMillis();
System.out.println(testTime(s2-s1));
System.out.println(redisService.getValueByKey("eeee9", "e9"));
}


二. 性能对比
两者的性能比较,如下图:
[img]https://img-blog.youkuaiyun.com/20150225174641279[/img]

三. 动态扩容
1. codis动态扩容
下图是整个codis的界面
[img]https://img-blog.youkuaiyun.com/20150225175821114[/img]

转自:http://blog.youkuaiyun.com/dayibagou/article/details/43937039
<think>好的,用户想了解RedisRedission的区别,主要集中在功能、性能使用场景的对比上。我之前已经回答过类似的问题,现在需要结合用户提供的站内引用内容来完善之前的回答。 首先,用户提供的引用[1]提到Redis的多机部署方案,比如主从+哨兵、Codis集群、Redis Cluster,以及高可用、扩展性能的区别。这部分内容可以补充到Redis的功能使用场景中,特别是主从同步的数据一致性问题,说明Redis是AP模型,只能保证最终一致性,这对理解其适用场景很重要。 引用[2]详细介绍了RedisRedission在分布式锁上的实现差异,包括Redission的功能、依赖配置使用方法。这部分可以进一步对比两者的分布式锁机制,比如Redission的自动续期、锁重试等功能,而原生Redis需要手动处理这些细节,从而突出Redission的便利性可靠性。 引用[3]提到了Redis的布隆过滤器,虽然用户的问题是关于RedisRedission的区别,但布隆过滤器作为Redis的一个功能模块,可以展示Redis原生功能与Redission可能提供的更高级封装之间的对比,比如Redission是否对布隆过滤器有更便捷的支持,或者性能上的优化。 接下来需要将这些引用内容整合到功能、性能使用场景的对比中。例如,在功能部分,强调Redis作为基础存储系统,支持多种数据结构部署方案,而Redission作为客户端库,提供更高级的分布式功能封装。在性能方面,引用[1]提到Redis的主从同步延迟可能影响性能,而Redission的抽象层损耗在大多数情况下可以忽略,结合引用[2]中的性能测试结果,说明两者在吞吐量上的接近。 使用场景部分,根据引用[1]中关于AP模型最终一致性的描述,适合需要高可用扩展的场景,而Redission更适合需要复杂分布式功能的场景,如分布式锁、信号量等。同时,引用[2]中的分布式锁缺陷可以补充到Redis的局限性中,而Redission如何解决这些问题。 此外,用户之前的问题生成了相关问题,可能需要考虑是否需要在当前回答中补充或调整这些问题,以更贴合新的引用内容。例如,关于数据一致性、部署方案的选择,或者布隆过滤器的使用等。 最后,确保回答结构清晰,对比明确,引用标注正确,并且语言自然流畅,符合用户要求的格式规范。</think>#### RedisRedission 的核心差异对比 --- ### 一、功能定位差异 1. **Redis** - **本质**:内存数据库,提供键值存储、多种数据结构(字符串、哈希、列表、集合、有序集合等)及持久化能力。 - **分布式支持**:通过主从复制、哨兵(Sentinel)、Cluster 集群等方案实现高可用扩展性[^1]。 - **数据一致性**:采用 AP 模型(可用性+分区容错性),主从同步存在时延,仅保证最终一致性[^1]。 - **原生功能限制**:需手动实现分布式锁逻辑(如 `SETNX` 命令设置锁、Lua 脚本保证原子性)、无自动续期机制,存在锁误删或死锁风险[^2]。 2. **Redission** - **本质**:基于 RedisJava 客户端库,封装分布式场景下的复杂操作。 - **分布式工具**:提供开箱即用的分布式锁(支持可重入锁、公平锁)、信号量、闭锁、分布式计数器等组件。 - **增强特性**: - **自动续期**:锁持有期间后台线程自动延长锁有效期,避免业务未完成时锁过期[^2]。 - **锁重试**:通过 Watchdog 机制监听锁状态,支持阻塞等待或重试获取锁。 - **故障恢复**:与 Redis Cluster 深度集成,支持节点故障自动切换。 --- ### 二、性能对比 | **维度** | **Redis** | **Redission** | |------------------|----------------------------------------|----------------------------------------| | **单操作延迟** | 原生命令直接执行,延迟极低(微秒级) | 增加客户端封装逻辑,延迟略高(毫秒级) | | **分布式锁性能** | 需手动实现原子性,并发竞争时可能频繁重试 | 内置优化算法(如红锁),减少无效竞争 | | **高并发场景** | 依赖开发者优化 Lua 脚本集群配置 | 通过连接池、异步 API 提升吞吐量 | **关键结论**: - Redission 的抽象层会引入约 5%~10% 的性能损耗,但在分布式锁等场景中,其优化机制(如批量操作、减少网络往返)可抵消损耗[^2][^3]。 - Redis Cluster 的横向扩展能力(如分片)是性能上限的核心因素,两者均受益于此[^1]。 --- ### 三、使用场景选择 | **场景** | **推荐方案** | **原因** | |------------------------------|-------------|--------------------------------------------------------------------------| | **简单键值存储/缓存** | Redis | 无需复杂功能,直接使用原生命令效率更高 | | **短期分布式锁(简单业务)** | Redis | 通过 `SETNX+EXPIRE` 可快速实现,代码轻量 | | **长期/复杂分布式锁** | Redission | 自动续期、可重入等特性避免锁失效,减少业务代码复杂度[^2] | | **分布式协作(如限流)** | Redission | 内置信号量、RateLimiter 等组件,API 更直观 | | **高一致性要求场景** | 慎用两者 | Redis 的 AP 模型可能不满足强一致性需求(如金融交易),需结合其他方案[^1] | --- ### 四、典型代码对比(分布式锁实现) ```java // 原生 Redis 实现(伪代码) Jedis jedis = new Jedis("redis-host"); String lockKey = "resource_lock"; String requestId = UUID.randomUUID().toString(); // 加锁(存在非原子性风险) if (jedis.setnx(lockKey, requestId) == 1) { jedis.expire(lockKey, 30); // 可能失败,导致死锁 try { // 执行业务逻辑... } finally { if (requestId.equals(jedis.get(lockKey))) { // 非原子操作,锁可能已过期 jedis.del(lockKey); } } } // Redission 实现 RLock lock = redissonClient.getLock(lockKey); try { lock.lock(30, TimeUnit.SECONDS); // 自动续期,无需手动设置过期 // 执行业务逻辑... } finally { lock.unlock(); // 释放锁原子操作 } ``` **缺陷对比**: - 原生 Redis 需自行处理原子性(如用 Lua 脚本合并 `SETNX+EXPIRE`),且无法自动处理锁续期[^2]。 - Redission 通过封装保证操作的原子性,并通过 Watchdog 线程每 10 秒检查锁状态,自动续期至业务完成[^2]。 --- ### 五、长期运维考量 | **维度** | **Redis** | **Redission** | |----------------|------------------------------|------------------------------| | **代码维护** | 需自行处理分布式逻辑,易出错 | 标准化 API,降低代码维护成本 | | **监控集成** | 依赖 Redis 原生监控指标 | 提供客户端级监控(如锁竞争统计)| | **升级影响** | 版本升级可能影响手动实现的逻辑| 跟随 Redission 版本迭代更新 | ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值