项目简介 1 项目背景 1.1 当前缓存的使用现状及问题 缓存云(统一Redis平台)来源于对缓存资源进行统一管理的需求,该需求最初从自动部署解决方案的讨论中衍生出来,解决运维的问题。目前,公司内部对缓存的使用存在如下问题和特点:
各个项目组单独部署缓存系统,有些项目组资源利用率不高;
各个项目组需要专人维护缓存系统的正常运行,这些人需要对缓存有很深的了解才能维护好这些系统;
各个项目组对缓存的使用方式不尽相同,往往需要自己开发某些程序来达到应用目的。
而JimDB则是缓存云的进一步技术创新 - 完全管理的分布式缓存与高速key/value存储服务。
1.2 如何解决这些问题 搭建缓存资源池,实施平台化的统一管理。解决缓存各自申请,缺少统一管理、统一监控、failover的功能等问题,通过统一化提高主机资源的利用率,便于运维管理。
JimDB后期规划对外提供公有云服务,支持ISV或普通开发者的应用。
2 JimDB的功能特性 2.1 支持大容量缓存 采用“pre-sharding”技术,将缓存数据分摊到多个分片(每个分片上具有相同的构成,比如:都是一主一从两个节点)上,从而可以创建出大容量的缓存。将来会利用集群技术创建大容量的缓存。
支持2种存储类型
Jimdb M(纯内存)
Jimdb S(内存+SSD两级存储)
选择Jimdb S版,可以存储10倍于内存容量的数据,并且提供更加可靠的持久性。
2.2 缓存数据的高可用性 和mysql相同,采用的也是异步复制,目前可以达到等同于mysql级别的数据可用性。
Jimdb S版支持命令级的同步复制,超过mysql级别的数据可用性。
可设置为自动的failover
2.3 支持多种I/O策略 支持读写分离、双写等I/O策略;针对读操作可分为“主优先”、“从优先”、“随机挑选”等方式;针对写操作可分为“同步写”和“异步写”。不同的I/O策略,对数据一致性的影响也不同,应用可以根据自身对数据一致性的需求,选择不同的I/O策略。
2.4 支持动态扩容 动态扩容有两种支持两种形式的动态扩容。第一种形式,通过在单个节点上预留内存,然后需要扩容时直接使用预留内存的方法达到扩容的目的;第二种形式,通过增加分片数并结 合数据迁移来达到扩容的目的。第一种形式和第二种形式可以结合使用。第一种方式对应用的影响最小,但扩容效果有限;第二种方式扩容效果好,但由于会引发数 据迁移,从而挤占网络带宽,会对应用有一定的影响。
2.5 支持特殊的命令及应用(spring-cache等) 目前已经支持了spring-cache与缓存的结合使用。将来会增加若干其他的特殊命令和应用。
3 如何使用 使用之前应申请JIMDB集群,拿到jimURL或者(configId,和token)
3.1 JAVA如何使用JIMDB 3.1.1 通过MAVEN引如JIMDB java客户端 1 2 3 4 5 6 7 8 9 10 <dependency > <groupId > com.jd.jim.cli</groupId > <artifactId > jim-cli-jedis</artifactId > <version > 1.4.5-SNAPSHOT</version > </dependency > <dependency > <groupId > com.jd.jim.cli</groupId > <artifactId > jim-cli-api</artifactId > <version > 1.4.5-SNAPSHOT</version > </dependency >
3.1.2 Spring环境下配置使用JIMDB CLIENT 注意:在系统退出时,要确保销毁spring容器上下文 spring 配置文件
1 2 3 <bean id ="jimClient" class ="com.jd.jim.cli.ReloadableJimClientFactoryBean" > <property name ="jimUrl" value ="jim://1803528671997086613/2" /> </bean >
java代码:
1 2 3 4 5 6 @Resource(name = "jimClient") private Cluster jimClient;public String getByKey (String key) { return jimClient.get(key); }
3.1.3 非Spring环境下使用JIMDB CLIENT 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 package com.jd.jim.cli.demo;import com.jd.jim.cli.Cluster;import com.jd.jim.cli.ReloadableJimClientFactory;public class JimClientDemo { public void close () { JimClientFactory.close(); } public String getByKey (String key) { return JimClientFactory.getJimClient().get(key); } private static class JimClientFactory { private static final ReloadableJimClientFactory clientFactory; private static final Cluster CLIENT_INSTANCE; static { clientFactory = new ReloadableJimClientFactory(); clientFactory.setJimUrl("jim://1803528671997086613/2" ); CLIENT_INSTANCE = clientFactory.getClient(); } public static Cluster getJimClient () { return CLIENT_INSTANCE; } public static void close () { if (clientFactory != null ) { clientFactory.clear(); } } } }
3.1.4 Spring-cache 注解方式 spring.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <bean id ="configClient" class ="com.jd.jim.cli.config.client.ConfigLongPollingClientFactoryBean" > <property name ="serviceEndpoint" value ="http://cfs.jim.jd.local" > </property > </bean > <bean id ="jimClient" class ="com.jd.jim.cli.ReloadableJimClientFactoryBean" > <property name ="configClient" ref ="configClient" > </property > <property name ="jimUrl" value ="jim://1803528818953446384/1" /> </bean > <bean id ="cacheManager" class ="com.jd.jim.cli.springcache.JimCacheManager" > <property name ="caches" > <list > <bean class ="com.jd.jim.cli.springcache.JimStringCache" > <property name ="keyPrefix" value ="cachetest_" /> <property name ="jimClient" ref ="jimClient" /> <property name ="entryTimeout" value ="60" /> <property name ="valueSerializer" > <bean class ="com.jd.jim.cli.serializer.DefaultStringSerializer" /> </property > </bean > </list > </property > </bean > <cache:annotation-driven cache-manager ="cacheManager" />
java 代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Cacheable(value = "cachetest_", key = "#key") public String getMessage (String key) { System.out.println("miss, get from db..." ); return "msg" ; } @CachePut(value = "cachetest_", key = "#key") public String setMessage (String key, String message) { return message; } @Caching(evict = { @CacheEvict(value = "cachetest_", key = "#key") }) public boolean delete (String key) { return true ; }