1. 程式人生 > >SpringMVC+Spring+mybatis+redis專案從零開始--redis快取策略和配置實現

SpringMVC+Spring+mybatis+redis專案從零開始--redis快取策略和配置實現


三.SSM專案-redis快取策略和配置實現

 距離上兩篇文章已過去蠻久了,為了響應各位網友的需求,最近把這個系列重新整理下。如有不足之處,請指正。

本章將實現redis快取策略和Spring整合redis配置。

1.     Redis簡單介紹

redis是一個key-value儲存系統。和Memcached類似,它支援儲存的value型別相對更多,包括string(字串)、list(連結串列)、set(集合)、zset(sortedset --有序集合)和hash(雜湊型別)。這些資料型別都支援push/pop、add/remove及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,redis支援各種不同方式的排序。與memcached一樣,為了保證效率,資料都是快取在記憶體中。區別的是redis會週期性的把更新的資料寫入磁碟或者把修改操作寫入追加的記錄檔案,並且在此基礎上實現了master-slave(主從)同步。

Redis是一個高效能的key-value資料庫。 redis的出現,很大程度補償了memcached這類key/value儲存的不足,在部 分場合可以對關係資料庫起到很好的補充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客戶端,使用很方便。

Redis支援主從同步。資料可以從主伺服器向任意數量的從伺服器上同步,從伺服器可以是關聯其他從伺服器的主伺服器。這使得Redis可執行單層樹複製。存檔可以有意無意的對資料進行寫操作。由於完全實現了釋出/訂閱機制,使得從資料庫在任何地方同步樹時,可訂閱一個頻道並接收主伺服器完整的訊息釋出記錄。同步對讀取操作的可擴充套件性和資料冗餘很有幫助。

----摘自百度百科

總結:

1.1  Redis是一個key-value儲存系統,支援多種儲存結構,如String,Hash,list,zset等;

1.2  Redis採用記憶體中資料集的形式,因此讀寫效能優異;

1.3  Redis支援資料持久化,支援AOF和RDB兩種持久化方式;

1.4  Redis類似mysql可以進行主從複製,可以實現讀寫分離;

1.5  Redis由於是記憶體中資料集儲存的,故對記憶體的要求較高,對海量資料處理有限制;

1.6  Redis主從複製時,由於宕機或其他情況一起,導致最後部分資料可能丟失。

2.     Redis快取策略

Redis和資料庫結合使用,使用策略如下:

2.1  讀取資料


2.2  更新資料—常用資料,變動性不強,併發不高


2.3  更新資料—併發較高


3.     Spring整合redis

3.1  applicationContext-redis.xml

spring與redis整合配置檔案

<?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:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">

	<!-- 連線池配置 -->
	<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
		<!-- 最大連線數 -->
		<property name="maxTotal" value="30" />
		<!-- 最大空閒連線數 -->
		<property name="maxIdle" value="10" />
		<!-- 每次釋放連線的最大數目 -->
		<property name="numTestsPerEvictionRun" value="1024" />
		<!-- 釋放連線的掃描間隔(毫秒) -->
		<property name="timeBetweenEvictionRunsMillis" value="30000" />
		<!-- 連線最小空閒時間 -->
		<property name="minEvictableIdleTimeMillis" value="1800000" />
		<!-- 連線空閒多久後釋放, 當空閒時間>該值 且 空閒連線>最大空閒連線數 時直接釋放 -->
		<property name="softMinEvictableIdleTimeMillis" value="10000" />
		<!-- 獲取連線時的最大等待毫秒數,小於零:阻塞不確定的時間,預設-1 -->
		<property name="maxWaitMillis" value="1500" />
		<!-- 在獲取連線的時候檢查有效性, 預設false -->
		<property name="testOnBorrow" value="true" />
		<!-- 在空閒時檢查有效性, 預設false -->
		<property name="testWhileIdle" value="true" />
		<!-- 連線耗盡時是否阻塞, false報異常,ture阻塞直到超時, 預設true -->
		<property name="blockWhenExhausted" value="false" />
	</bean>	
	
	<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
		<constructor-arg name="host" value="${redis.ip}"></constructor-arg>
		<constructor-arg name="port" value="${redis.port}"></constructor-arg>
		<constructor-arg name="poolConfig" ref="jedisPoolConfig"></constructor-arg>
	</bean>
</beans>

3.2  redisDao介面和實現

簡單通過redis實現增刪改查

package com.ssm.manager.dao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import redis.clients.jedis.JedisPool;

@Repository("redisDao")
public class RedisDaoImpl implements RedisDao {

	@Autowired
	private JedisPool jedisPool;
	@Override
	public String get(String key) {
		return jedisPool.getResource().get(key);
	}

	@Override
	public String set(String key, String value) {
		return jedisPool.getResource().set(key,value);
	}

	@Override
	public String hget(String hkey, String key) {
		return jedisPool.getResource().hget(hkey, key);
	}

	@Override
	public long hset(String hkey, String key, String value) {
		return jedisPool.getResource().hset(hkey, key,value);
	}

}

3.3  UserServiceImpl實現 

實現User業務,先查redis,如果不存在從資料庫獲取,然後把相關資訊寫入到redis

package com.ssm.manager.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.ssm.commons.JacksonUtils;
import com.ssm.manager.dao.RedisDao;
import com.ssm.manager.mapper.UserMapper;
import com.ssm.manager.pojo.User;

@Service
public class UserServiceImpl implements UserService {

	@Autowired
	private UserMapper userMapper;
	
	@Autowired
	private RedisDao redisDao;
	@Override
	public List<User> getUsers() {
		return userMapper.getUsers();
	}

	@Override
	public void insertUser(User user) {
		
		userMapper.insertUser(user);
		String userJson = redisDao.get("user_" + user.getId());
		if(StringUtils.isEmpty(userJson)){
			redisDao.set("user_" + user.getId(), JacksonUtils.objectToJson(user));
		}
		
	}

	@Override
	public User getUserById(String id) {
		String userJson = redisDao.get("user_" + id);
		User user = null;
		if(StringUtils.isEmpty(userJson)){
			user = userMapper.getUserById(id);
			//不存在,設定
			if(user != null)
				redisDao.set("user_" + id, JacksonUtils.objectToJson(user));
		}else{
			user = JacksonUtils.jsonToPojo(userJson, User.class);
		}
		return user;
	}

}

4.     單元測試 

package com.ssm.test;

import java.util.List;

import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.ssm.manager.pojo.User;
import com.ssm.manager.service.UserService;

public class ssmTest {
	
	private ApplicationContext ctx = null;
	private UserService userService = null;
	
	@Before
	public void init()
	{
		ctx = new ClassPathXmlApplicationContext("spring/applicationContext-service.xml");
		userService = ctx.getBean(UserService.class);
	}
	
	@Test	
	public void testGetUsers(){
		List<User> users = userService.getUsers();
		System.out.println(users);
	}
	
	@Test
	public void testInsertUser(){
		User user = new User();
		user.setPassword("123");
		user.setUserName("ssm1111");
		
		userService.insertUser(user);
	}
	
	@Test
	public void testGetUserById(){
		String id="4";
		System.out.println(userService.getUserById(id));
		
	}
	
	

}

5.     總結

本章簡單的介紹Spring與redis框架jedis整合。如果需要也可以考慮通過spring data redis去整合.

後續本來也會通過springboot+spring data redis的例項來實現redis。

 6.  程式碼路徑