方案一:
程序同时写Redis和MySQL
读Redis
方案二:
程序写MySQL, 使用Gearman调用MySQL的UDF,完成对Redis的写
读Redis
方案三:
程序写MySQL, 解析binlog,数据放入队列写Redis
读Redis
方案四:
程序写Redis,并将写放入MQ写MySQL
读Redis
redis和mysql结合
首先声明一下,我是在一个SSM项目的基础上进行优化的,所以就不进行基础的介绍了。
redis:
内存型数据库,有持久化功能,具备分布式特性,可靠性高,适用于对 读写效率要求都很高 ,数据处理 业务复杂和对安全性要求较高 的系统(如新浪微博的计数和微博发布部分系统,对数据安全性、读写要求都很高)。
reids的安装很简单,我会在文末附上文件地址,只需要解压缩,然后点击打开redis-server.exe即可
下面正式开始:
1.pom.xml文件添加如下 :
<!--redis-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.5.2.RELEASE</version>
</dependency>
2.redis.properties
# Redis settings
redis.host=127.0.0.1
redis.port=6379
#redis.pass=password
redis.dbIndex=0
redis.expiration=3000
redis.maxIdle=300
redis.maxActive=600
redis.maxWait=1000
redis.testOnBorrow=true
3.database.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8
username=###
password=###
#\u5b9a\u4e49\u521d\u59cb\u8fde\u63a5\u6570
initialSize=10
#\u5b9a\u4e49\u6700\u5927\u8fde\u63a5\u6570
maxActive=20
#\u5b9a\u4e49\u6700\u5927\u7a7a\u95f2
maxIdle=20
#\u5b9a\u4e49\u6700\u5c0f\u7a7a\u95f2
minIdle=1
#\u5b9a\u4e49\u6700\u957f\u7b49\u5f85\u65f6\u95f4
maxWait=60000
timeBetweenEvictionRunsMillis=300000
4..spring-mybatis.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="#34;
xmlns:xsi="#34; xmlns:p="#34;
xmlns:context="#34;
xmlns:mvc="#34; xmlns:aop="#34;
xmlns:tx="#34;
xsi:schemaLocation="
#34;>
<!--导入MyBatis和redis的信息配置-->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:database.properties</value>
<value>classpath:redis.properties</value>
</list>
</property>
</bean>
<!-- 自动扫描 -->
<context:component-scan base-package="com.hanpeng" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
<!-- 初始化连接大小 -->
<property name="initialSize" value="${initialSize}"></property>
<!-- 连接池最大数量 -->
<property name="maxActive" value="${maxActive}"></property>
<!-- 连接池最大空闲 -->
<property name="maxIdle" value="${maxIdle}"></property>
<!-- 连接池最小空闲 -->
<property name="minIdle" value="${minIdle}"></property>
<!-- 获取连接最大等待时间 -->
<property name="maxWait" value="${maxWait}"></property>
<!-- 空闲连接回收 -->
<property name="timeBetweenEvictionRunsMillis" value="${timeBetweenEvictionRunsMillis}"/>
<!-- 每次取出连接是否进行测试,如果为true,影响性能 -->
<property name="testOnBorrow" value="false"/>
<!-- 测试连接执行的sql -->
<property name="validationQuery" value="SELECT 1" />
<!-- 空闲时是否进行验证,检查对象是否有效,默认为false -->
<property name="testWhileIdle" value="true"/>
</bean>
<!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- 自动扫描mapping.xml文件 -->
<property name="mapperLocations" value="classpath*:mapping/**/*.xml"></property>
<property name="configLocation" value="mybatis-config.xml"></property>
<!--pageHelper-->
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<!--使用下面的方式配置参数,一行配置一个 -->
<value>
helperDialect=postgresql
reasonable=true
supportMethodsArguments=true
params=count=countSql
autoRuntimeDialect=true
</value>
</property>
</bean>
</array>
</property>
</bean>
<!-- DAO接口所在包名,Spring会自动查找其下的类 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.hanpeng" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>
<!-- basedao使用 -->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"
scope="prototype">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean>
<!-- (事务管理)transaction manager, use JtaTransactionManager for global tx -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- set leval -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- all methods starting with 'get' are read-only -->
<tx:method name="get*" read-only="true" />
<tx:method name="list*" read-only="true" />
<tx:method name="query*" read-only="true" />
<tx:method name="search*" read-only="true" />
<tx:method name="find*" read-only="true" />
<tx:method name="check*" read-only="true" />
<tx:method name="newLog*" propagation="NOT_SUPPORTED" />
<!-- other methods use the default transaction settings -->
<tx:method name="*" rollback-for="Exception" /> <!-- all exception rollback -->
</tx:attributes>
</tx:advice>
<!-- transaction config related... end -->
<!-- redis config start -->
<!-- 配置JedisPoolConfig实例 -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxTotal" value="${redis.maxActive}" />
<property name="maxWaitMillis" value="${redis.maxWait}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<!-- 配置JedisConnectionFactory -->
<bean id="jedisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="hostName" value="${redis.host}" />
<property name="port" value="${redis.port}" />
<!-- <property name="password" value="${redis.pass}" /> -->
<property name="database" value="${redis.dbIndex}" />
<property name="poolConfig" ref="poolConfig" />
</bean>
<!-- 配置RedisTemplate -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory" />
</bean>
<!-- 配置RedisCacheManager -->
<bean id="redisCacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
<constructor-arg ref="redisTemplate" />
<property name="defaultExpiration" value="${redis.expiration}" />
</bean>
<!-- 配置RedisCacheConfig -->
<bean id="redisCacheConfig" class="com.jd.service.RedisCacheConfig">
<constructor-arg ref="jedisConnectionFactory" />
<constructor-arg ref="redisTemplate" />
<constructor-arg ref="redisCacheManager" />
</bean>
<!-- redis config end -->
</beans>
5.缓存主要在service层进行,查询的结果会缓存,把对象序列号存到redis中去,key就是注解中的参数 ,
例如@Cacheable(“findUsers”): 存在redis中的key就是findUsers。缓存了这个结果之后再次请求这个方法就不会去数据库中查,而是从redis缓存中读取数据,这样就减少了跟数据库之间的交互。然后修改、删除、增加操作就会清除缓存,保持数据的一致性。
RedisCacheConfig: 需要增加这个配置类,会在applicationContex配置文件中注册这个bean。
package com.jd.service;
import java.lang.reflect.Method;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
/**
* @program: cloudConnectWMS
* @description: redis配置类(通过spring管理redis缓存配置)
* @author: by hanpeng
* @create: 2018-12-14 11:27
**/@Configuration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport {
private volatile JedisConnectionFactory jedisConnectionFactory;
private volatile RedisTemplate<String, String> redisTemplate;
private volatile RedisCacheManager redisCacheManager;
public RedisCacheConfig() {
super();
}
/**
* 带参数的构造方法 初始化所有的成员变量
*
* @param jedisConnectionFactory
* @param redisTemplate
* @param redisCacheManager
*/ public RedisCacheConfig(JedisConnectionFactory jedisConnectionFactory, RedisTemplate<String, String> redisTemplate,
RedisCacheManager redisCacheManager) {
this.jedisConnectionFactory = jedisConnectionFactory;
this.redisTemplate = redisTemplate;
this.redisCacheManager = redisCacheManager;
}
public JedisConnectionFactory getJedisConnecionFactory() {
return jedisConnectionFactory;
}
public RedisTemplate<String, String> getRedisTemplate() {
return redisTemplate;
}
public RedisCacheManager getRedisCacheManager() {
return redisCacheManager;
}
@Bean
public KeyGenerator customKeyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... objects) {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : objects) {
sb.append(obj.toString());
}
return sb.toString();
}
};
}
}
6.UserServiceImpl
import java.util.List;
import javax.annotation.Resource;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
/**
* userService
*
* @Cacheable("a")注解的意义就是把该方法的查询结果放到redis中去,下一次再发起查询就去redis中去取,存在redis中的数据的key就是a;
* @CacheEvict(value={"a","b"},allEntries=true) 的意思就是执行该方法后要清除redis中key名称为a,b的数据;
*/@Service("userService")
@Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)
public class UserServiceImpl implements IUserService {
@Resource
private UserMapper iUserDao;
@Cacheable("getUserById") //标注该方法查询的结果进入缓存,再次访问时直接读取缓存中的数据
@Override
public User getUserById(int userId) {
return this.iUserDao.selectByPrimaryKey(userId);
}
@Cacheable("getAllUser")
@Override
public List<User> getAllUser() {
return this.iUserDao.selectAllUser();
}
@CacheEvict(value= {"getAllUser","getUserById","findUsers"},allEntries=true)//清空缓存,allEntries变量表示所有对象的缓存都清除
@Override
public void insertUser(User user) {
this.iUserDao.insertUser(user);
}
@CacheEvict(value= {"getAllUser","getUserById","findUsers"},allEntries=true)
@Override
public void deleteUser(int id) {
this.iUserDao.deleteUser(id);
}
@Cacheable("findUsers")
@Override
public List<User> findUsers(String keyWords) {
return iUserDao.findUsers(keyWords);
}
@CacheEvict(value= {"getAllUser","getUserById","findUsers"},allEntries=true)
@Override
public void editUser(User user) {
this.iUserDao.editUser(user);
}
}
总结;文章内容仅代表个人观点,如有不正之处,欢迎批评指正,谢谢大家。
不积跬步无以至千里,学习C/C++,Linux,Nginx,golang,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,ffmpeg,流媒体, 音视频,CDN,P2P,K8S,Docker,Golang,TCP/IP,协程,嵌入式,ARM,DPDK等等。。。
可以后台私信‘资料’即可领取相关学习资料