虚拟与真实--VMware虚拟化入门篇
样例视频地址:http://www.roncoo.com/course/view/ec2dc65e93da408ab70cf9ead80777f8 关注公众号:
大家在工作中可能会遇到这样的需求,即Redis读写分离,目的是为了压力分散化。下面我将为大家介绍借助AWS的ELB实现读写分离,以写主读从为例。
<!-- redis客户端 --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.6.2</version> </dependency>
此类的目的是为读和写分别配置不同的注解,用来区分是主还是从。
package com.silence.spring.redis.readwriteseparation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/**
* Created by keysilence on 16/10/26.
*/@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface JedisPoolSelector {
String value();
}
此类的目的是针对主和从的注解,进行动态链接池调配,即主的使用主链接池,从的使用从连接池。
package com.silence.spring.redis.readwriteseparation;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.annotation.Pointcut;import org.aspectj.lang.reflect.MethodSignature;import org.springframework.beans.BeansException;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import redis.clients.jedis.JedisPool;import javax.annotation.PostConstruct;import java.lang.reflect.Method;import java.util.Date;/**
* Created by keysilence on 16/10/26.
*/@Aspectpublic class JedisPoolAspect implements ApplicationContextAware {
private ApplicationContext ctx; @PostConstruct
public void init() {
System.out.println("jedis pool aspectj started @" + new Date());
} @Pointcut("execution(* com.silence.spring.redis.readwriteseparation.util.*.*(..))") private void allMethod() {
} @Before("allMethod()") public void before(JoinPoint point)
{
Object target = point.getTarget();
String method = point.getSignature().getName();
Class classz = target.getClass();
Class<?>[] parameterTypes = ((MethodSignature) point.getSignature())
.getMethod().getParameterTypes(); try {
Method m = classz.getMethod(method, parameterTypes); if (m != null && m.isAnnotationPresent(JedisPoolSelector.class)) {
JedisPoolSelector data = m
.getAnnotation(JedisPoolSelector.class);
JedisPool jedisPool = (JedisPool) ctx.getBean(data.value());
DynamicJedisPoolHolder.putJedisPool(jedisPool);
}
} catch (Exception e) {
e.printStackTrace();
}
} public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.ctx = applicationContext;
}
}
此类目的是存储当前使用的JedisPool,即上面类赋值后的结果保存。
package com.silence.spring.redis.readwriteseparation;import redis.clients.jedis.JedisPool;/**
* Created by keysilence on 16/10/26.
*/public class DynamicJedisPoolHolder {
public static final ThreadLocal<JedisPool> holder = new ThreadLocal<JedisPool>(); public static void putJedisPool(JedisPool jedisPool) {
holder.set(jedisPool);
} public static JedisPool getJedisPool() { return holder.get();
}
}
此类目的是对Redis具体的调用,里面包含使用主还是从的方式调用。
package com.silence.spring.redis.readwriteseparation.util;import com.silence.spring.redis.readwriteseparation.DynamicJedisPoolHolder;import com.silence.spring.redis.readwriteseparation.JedisPoolSelector;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/**
* Created by keysilence on 16/10/26.
*/public class RedisUtils {
private static Logger logger = LoggerFactory.getLogger(RedisUtils.class);
@JedisPoolSelector("master")
public String setString(final String key, final String value) {
String ret = DynamicJedisPoolHolder.getJedisPool().getResource().set(key, value);
System.out.println("key:" + key + ",value:" + value + ",ret:" + ret);
return ret;
}
@JedisPoolSelector("slave")
public String get(final String key) {
String ret = DynamicJedisPoolHolder.getJedisPool().getResource().get(key);
System.out.println("key:" + key + ",ret:" + ret);
return ret;
}
}
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig"> <!-- 池中最大链接数 --> <property name="maxTotal" value="100"/> <!-- 池中最大空闲链接数 --> <property name="maxIdle" value="50"/> <!-- 池中最小空闲链接数 --> <property name="minIdle" value="20"/> <!-- 当池中链接耗尽,调用者最大阻塞时间,超出此时间将跑出异常。(单位:毫秒;默认为-1,表示永不超时) --> <property name="maxWaitMillis" value="1000"/> <!-- 参考:http://biasedbit.com/redis-jedispool-configuration/ --> <!-- 调用者获取链接时,是否检测当前链接有效性。无效则从链接池中移除,并尝试继续获取。(默认为false) --> <property name="testOnBorrow" value="true" /> <!-- 向链接池中归还链接时,是否检测链接有效性。(默认为false) --> <property name="testOnReturn" value="true" /> <!-- 调用者获取链接时,是否检测空闲超时。如果超时,则会被移除(默认为false) --> <property name="testWhileIdle" value="true" /> <!-- 空闲链接检测线程一次运行检测多少条链接 --> <property name="numTestsPerEvictionRun" value="10" /> <!-- 空闲链接检测线程检测周期。如果为负值,表示不运行检测线程。(单位:毫秒,默认为-1) --> <property name="timeBetweenEvictionRunsMillis" value="60000" /> <!-- 链接获取方式。队列:false;栈:true --> <!--<property name="lifo" value="false" />--> </bean> <bean id="master" class="redis.clients.jedis.JedisPool"> <constructor-arg index="0" ref="poolConfig"/> <constructor-arg index="1" value="192.168.100.110" type="java.lang.String"/> <constructor-arg index="2" value="6379" type="int"/> </bean> <bean id="slave" class="redis.clients.jedis.JedisPool"> <constructor-arg index="0" ref="poolConfig"/> <!-- 此处Host配置成ELB地址 --> <constructor-arg index="1" value="192.168.100.110" type="java.lang.String"/> <constructor-arg index="2" value="6380" type="int"/> </bean> <bean id="redisUtils" class="com.silence.spring.redis.readwriteseparation.util.RedisUtils"> </bean> <bean id="jedisPoolAspect" class="com.silence.spring.redis.readwriteseparation.JedisPoolAspect" /> <aop:aspectj-autoproxy proxy-target-class="true"/></beans>
package com.silence.spring.redis.readwriteseparation;import com.silence.spring.redis.readwriteseparation.util.RedisUtils;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;/**
* Created by keysilence on 16/10/26.
*/public class Test {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-datasource.xml");
System.out.println(ctx);
RedisUtils redisUtils = (RedisUtils) ctx.getBean("redisUtils");
redisUtils.setString("aaa", "111");
System.out.println(redisUtils.get("aaa"));
}
}
与方式一类似,但是需要写死具体使用主的池还是从的池,思路如下:
放弃注解的方式,直接将主和从的两个链接池注入到具体实现类中。
package com.silence.spring.redis.readwriteseparation.util;import com.silence.spring.redis.readwriteseparation.DynamicJedisPoolHolder;import com.silence.spring.redis.readwriteseparation.JedisPoolSelector;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import redis.clients.jedis.JedisPool;/**
* Created by keysilence on 16/10/26.
*/public class RedisUtils {
private static Logger logger = LoggerFactory.getLogger(RedisUtils.class); private JedisPool masterJedisPool; private JedisPool slaveJedisPool; public void setMasterJedisPool(JedisPool masterJedisPool) { this.masterJedisPool = masterJedisPool;
} public void setSlaveJedisPool(JedisPool slaveJedisPool) { this.slaveJedisPool = slaveJedisPool;
} public String setString(final String key, final String value) {
String ret = masterJedisPool.getResource().set(key, value);
System.out.println("key:" + key + ",value:" + value + ",ret:" + ret); return ret;
} public String get(final String key) {
String ret = slaveJedisPool.getResource().get(key);
System.out.println("key:" + key + ",ret:" + ret); return ret;
}
}
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig"> <!-- 池中最大链接数 --> <property name="maxTotal" value="100"/> <!-- 池中最大空闲链接数 --> <property name="maxIdle" value="50"/> <!-- 池中最小空闲链接数 --> <property name="minIdle" value="20"/> <!-- 当池中链接耗尽,调用者最大阻塞时间,超出此时间将跑出异常。(单位:毫秒;默认为-1,表示永不超时) --> <property name="maxWaitMillis" value="1000"/> <!-- 参考:http://biasedbit.com/redis-jedispool-configuration/ --> <!-- 调用者获取链接时,是否检测当前链接有效性。无效则从链接池中移除,并尝试继续获取。(默认为false) --> <property name="testOnBorrow" value="true" /> <!-- 向链接池中归还链接时,是否检测链接有效性。(默认为false) --> <property name="testOnReturn" value="true" /> <!-- 调用者获取链接时,是否检测空闲超时。如果超时,则会被移除(默认为false) --> <property name="testWhileIdle" value="true" /> <!-- 空闲链接检测线程一次运行检测多少条链接 --> <property name="numTestsPerEvictionRun" value="10" /> <!-- 空闲链接检测线程检测周期。如果为负值,表示不运行检测线程。(单位:毫秒,默认为-1) --> <property name="timeBetweenEvictionRunsMillis" value="60000" /> <!-- 链接获取方式。队列:false;栈:true --> <!--<property name="lifo" value="false" />--> </bean> <bean id="masterJedisPool" class="redis.clients.jedis.JedisPool"> <constructor-arg index="0" ref="poolConfig"/> <constructor-arg index="1" value="192.168.100.110" type="java.lang.String"/> <constructor-arg index="2" value="6379" type="int"/> </bean> <bean id="slaveJedisPool" class="redis.clients.jedis.JedisPool"> <constructor-arg index="0" ref="poolConfig"/> <constructor-arg index="1" value="192.168.100.110" type="java.lang.String"/> <constructor-arg index="2" value="6380" type="int"/> </bean> <bean id="redisUtils" class="com.silence.spring.redis.readwriteseparation.util.RedisUtils"> <property name="masterJedisPool" ref="masterJedisPool"/> <property name="slaveJedisPool" ref="slaveJedisPool"/> </bean></beans>
微信关注我们
转载内容版权归作者及来源网站所有!
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。
为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。
Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。
Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。