本文带大家入门市场上最佳的redis实践方案,redisson+codis。
一、为什么要使用redisson
这里介绍的是redis客户端方面的。
对于java客户端,现在市面上有jedis,jedis是redis官方推荐的,支持redisCluster、shardJedis、redis sentinel等多种功能。功能比较齐全。虽然都支持,但是redisCluster、redis sentinel都有各自的缺点,下面会介绍,那么支持也没有。shardjedis也是有缺点,因为每次增加减少或者修改redis服务器的ip,shardjedis都需要改变ip,这个是很麻烦的事情,下面也会介绍。
真正需要使用redisson的原因如下:参考
jedis使用阻塞的I/O,且其方法调用都是同步的,程序需要等到sockets处理完I/O才能执行,不支持异步。jedis客户端实例不是线程安全的,所以需要通过连接池来使用jedis;redisson使用非阻塞的I/O和基于netty的时间驱动的通讯层,其方法调用是异步的。Redisson的API是线程安全的,所以可以操作单个redission连接来完成各种操作。
所以,当数据量上来了之后,redisson的优点就体现出来了。
但是redisson也不能解决的一个问题就是服务器ip增加减少或者修改客户端都需要重新配置,解决的办法就是用下面的代理codis。
二、为什么要使用codis
这里介绍的是redis服务端方面的。
首先我们分析市面上几款产品:
redis sentinel:redis官方高可用的实现方案,数据量起来了之后,数据放在单台机器上会遇到容量和qps的瓶颈。redis sentinel只能实现高可用,不能实现不同的数据分布在不同的机器上。
redis cluster:redis官方集群实现方案,把槽slot分配给各个机器,数据再放到各个槽里面。可以实现分布式,每台单独的机器可以配置一个从节点,可以实现高可用。但是如果机器的ip和端口改变了,客户端的代码或者配置是需要修改的,在实际生产环境中使用会很苦恼。
shardjedis:这个其实属于的是客户端方面。但是因为它实现了hash一致性算法,并且使用了虚拟节点解决了节点分配不均的问题,这种一般是服务端解决的,所以放这里。并且添加或者减少节点的时候,只影响相邻的节点,这种用一致性hash实现的方法可以说是很优秀了,但是出现的问题和redis cluster 问题一样,如果机器的ip和端口改变了,需要修改配置。并且客户端分片,有多个客户端,容易造成数据的错误。
cachecloud:cachecloud是搜狐tv开发的,作为redis客户端服务器解决方案其实是不错的,服务端提供一个应用id,客户端连接这个id就可以。服务端修改ip和端口或者迁移数据对客户端都是透明的,客户端只要连接那个id就可以,所以可以解决我们遇到的所有问题。但是,使用这个方案总感觉有点跟不上主流,因为主流都用redisson或者jedis,客户端需要自己上传一个jar包到maven上面,然后在项目里面使用,如果这个使用熟悉了,就失去使用别的主流框架的机会,不过这个东西还是很好用。
Twemproxy:github地址,说实话,这个东西也是很常用的redisproxy方案,而且twitter开发的,必出精品,但是正如codis的git界面所展示的,codis是更加优秀:
twemproxy最大的缺点就是,reshard(迁移槽数据)之后,需要重启集群,这也是很难接受的;另外也没有图形界面。
哈哈哈,我们还是支持豌豆荚国产牌子吧
codis:这个就是codis,
参考
codis解决了如下问题:
通过1024个槽进行rehash从而可以平滑扩容缩容、避免单点故障和单点性能不足(高可用)、有图形界面、服务端操作对客户端透明、可以轻松将twemproxy迁移到codis。
codis唯一的瑕疵是 需要更改redis的源代码(为了加入slot信息),所以codis启动的是codis-server而不是redis-server
阿里的redis集群解决方案:阿里云,或者别的云,一般都有redis的集群解决方案,如果有钱并且对安全性要求不是特别特别高(需要使用自己的机房),直接用他们的解决方案就行了。
总结起来,如果数据量不大,直接使用redis-sentinel或者客户端分片的sharding jedis都可以了。但是要实现大规模数据,同时保证安全性(需要有自己的机房)又要便宜那就用redisson+codis。
三、如何使用redisson
1、先写一个redissonManager
public class RedissonManager { | |
private Config config = new Config(); | |
private Redisson redisson = null; | |
public Redisson getRedisson() { | |
return redisson; | |
} | |
private static String redis1Ip = PropertiesUtil.getProperty("redis1.ip"); | |
private static Integer redis1Port = Integer.parseInt(PropertiesUtil.getProperty("redis1.port")); | |
private static String redis2Ip = PropertiesUtil.getProperty("redis2.ip"); | |
private static Integer redis2Port = Integer.parseInt(PropertiesUtil.getProperty("redis2.port")); | |
@PostConstruct | |
private void init(){ | |
try { | |
config.useSingleServer().setAddress(new StringBuilder().append(redis1Ip).append(":").append(redis1Port).toString()); | |
redisson = (Redisson) Redisson.create(config); | |
log.info("初始化Redisson结束"); | |
} catch (Exception e) { | |
log.error("redisson init error",e); | |
} | |
} | |
把要使用的配置加入,如果有两个ip,可以加入两个
然后,这个就是使用方法:
public class RedissonTest { | |
private static final String CLOSE_ORDER_TASK_LOCK= "LOOK"; | |
public static void main(String[] args) { | |
RedissonManager redissonManager = new RedissonManager(); | |
RLock lock = redissonManager.getRedisson().getLock(CLOSE_ORDER_TASK_LOCK); | |
boolean getLock = false; | |
try { | |
if(getLock = lock.tryLock(0,50, TimeUnit.SECONDS)){ | |
log.info("Redisson获取到分布式锁:{},ThreadName:{}",CLOSE_ORDER_TASK_LOCK,Thread.currentThread().getName()); | |
int hour = Integer.parseInt(PropertiesUtil.getProperty("close.order.task.time.hour","2")); | |
// iOrderService.closeOrder(hour); | |
}else{ | |
log.info("Redisson没有获取到分布式锁:{},ThreadName:{}", CLOSE_ORDER_TASK_LOCK,Thread.currentThread().getName()); | |
} | |
} catch (InterruptedException e) { | |
log.error("Redisson分布式锁获取异常",e); | |
} finally { | |
if(!getLock){ | |
return; | |
} | |
lock.unlock(); | |
log.info("Redisson分布式锁释放锁"); | |
} | |
} |
四、如何使用codis
首先了解下codis,对codis的搭建心中有数,简单的codis图
最关键的就是proxy,codis-proxy为redis的代理,通过这个代理,redis客户端可以实现对redis服务器的访问。服务器的修改变化数据迁移等对客户端来说都是透明的。proxy可以实现HA。
接下去就是codis-redis-group,codis把redis分成多个group,每个group实际只能有一个master,master可以有多个slave,也就是codis的容量实际取决于group的多少。
再看一张完整的图片
codis是通过zookeeper协同数据的,另外还提供了dashboard方便用户管理集群,codis FE图形界面处理。codis adming 集群管理的命令行工具。
然后安装codis就看到如下界面:
可以看到,我们的proxy在19000端口启动,admin在11080端口启动。
又两个分组,一个占用513个slot,另外一个暂用511个slot
第一个group有两个redis,6381为master,6382为slave,可以在绿色的setting设置;第二个group只有6383一个服务器。上面会有new group添加group,add server把server添加到group里面。
如果需要使用多台机器,每台机器的zookeeper配置彼此即可,参考
五、如何结合使用redisson+codis
怎么使用,直接把19000这个proxy的端口放到redisson的port的配置里面即可。