很多情況我們?yōu)榱私鉀Q并發(fā)問題使用redis非關(guān)系型數(shù)據(jù)庫保存數(shù)據(jù)德崭,我們序列化保存熱點(diǎn)數(shù)據(jù)的傳輸可以隨時(shí)把對(duì)象持久化到數(shù)據(jù)庫、文件等系統(tǒng)里揖盘,也方便我們反序列化獲取對(duì)象眉厨,從而提高用戶體驗(yàn)和系統(tǒng)性能
1.利用maven管理項(xiàng)目,導(dǎo)入相關(guān)jar包
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.dyuproject.protostuff</groupId>
<artifactId>protostuff-core</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>com.dyuproject.protostuff</groupId>
<artifactId>protostuff-runtime</artifactId>
<version>1.1.1</version>
</dependency>
2.編寫protostuff工具類兽狭,實(shí)現(xiàn)對(duì)象序列化和反序列化
import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtostuffIOUtil;
import com.dyuproject.protostuff.Schema;
import com.dyuproject.protostuff.runtime.RuntimeSchema;
import lombok.extern.slf4j.Slf4j;
/**
* protostuff序列化工具
*
* @auth liubing
* @date 2018-03-22
*/
@Slf4j
public class ProtostuffUtil {
public ProtostuffUtil() {
}
/**
* 對(duì)象序列化
* @paramo 需要序列化對(duì)象
* @param 序列化對(duì)象類型
* @return
*/
public static byte[] serializer(T o) {
// 通過對(duì)象的類構(gòu)建對(duì)應(yīng)的schema
Schema schema= RuntimeSchema.createFrom(o.getClass());
// 將對(duì)象通過動(dòng)態(tài)生成的schema轉(zhuǎn)換成字節(jié)數(shù)組
// LinkedBuffer用于緩存較大的對(duì)象
return ProtostuffIOUtil.toByteArray(o, schema, LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE));
}
/**
* 對(duì)象反序列化
* @parambytes 對(duì)象字節(jié)數(shù)組
* @paramclazz Class對(duì)象
* @param 反序列化對(duì)象
* @return
*/
public static T deserializer(byte[] bytes, Class clazz) {
T obj= null;
try {
// 通過對(duì)象的類構(gòu)建對(duì)應(yīng)的schema憾股;
Schema schema= RuntimeSchema.createFrom(clazz);
// 通過schema新建一個(gè)對(duì)象,這里需要轉(zhuǎn)換一下
obj= (T) schema.newMessage();
// 數(shù)據(jù)反序列化
ProtostuffIOUtil.mergeFrom(bytes, obj, schema);
} catch (Exception e) {
log.error(e.getMessage(),e);
}
return obj;
}
}
3.redis 數(shù)據(jù)庫操作
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisSentinelPool;
/**
* 思路:
* 1.查找數(shù)據(jù)時(shí),首先向Redis緩存中查找.
* 2.如果找不到,就轉(zhuǎn)向數(shù)據(jù)庫中查找.
* 2.1將查找到的數(shù)據(jù)放進(jìn)Redis緩存中
* 3.返回查找到的對(duì)象
*
* Created by liubing on 2018/3/21.
*/
@Slf4j
@Repository
public class RedisCacheDao {
@Autowired
private JedisSentinelPool jedisSentinelPool;
/**
* 從redis中查找數(shù)據(jù)
* @paramsecKillId
* @return查詢到的對(duì)象
*/
public SecKill getSecKill(Long secKillId){
// 邏輯
Jedis jedis= jedisSentinelPool.getResource();
try {
String key= "secKill_" + secKillId;
// 從Jedis中獲取序列化的字節(jié)數(shù)組
byte[] bytes= jedis.get(key.getBytes());
if (bytes!= null) {
// 將字節(jié)數(shù)組再反序列化SecKill
SecKill secKill= ProtostuffUtil.deserializer(bytes, SecKill.class);
// secKill被反序列化
return secKill;
}
}finally {
jedis.close();
}
return null;
}
/**
* 將對(duì)象放入redis中
* @paramsecKill
* @return如果在鍵中設(shè)置了值則返回OK箕慧。如果值未設(shè)置則返回null
*/
public String putSecKill(SecKill secKill){
// 邏輯
try {
Jedis jedis= jedisSentinelPool.getResource();
try {
String key= "secKill_" + secKill.getSecKillId();
// 將對(duì)象轉(zhuǎn)換成字節(jié)數(shù)組
byte[] bytes= ProtostuffUtil.serializer(secKill);
// 超時(shí)緩存
// Redis存儲(chǔ)數(shù)據(jù)可以是永久的或是時(shí)限的
// 對(duì)于數(shù)據(jù)庫緩存來說,一般使用超時(shí)機(jī)制來保證數(shù)據(jù)緩存與數(shù)據(jù)庫數(shù)據(jù)的完整性
int timeout= 60*60;
String result= jedis.setex(key.getBytes(),timeout,bytes);
return result;
} finally {
jedis.close();
}
} catch (Exception e){
log.error(e.getMessage(),e);
}
return null;
}
}
使用哨兵機(jī)制redis服務(wù)服球,配置文件如下:
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;
import java.util.HashSet;
import java.util.Set;
/**
* @auth liubing
* @date 2018-03-22
*/
@Configuration
@Slf4j
public class RedisSourceConfig {
@Value("${redis.maxActive}")
private String maxActive;
@Value("${redis.maxIdle}")
private String maxIdle;
@Value("${redis.minIdle}")
private String minIdle;
@Value("${redis.sentinel.host}")
private String sentinelHost;
@Value("${redis.sentinel.port}")
private String sentinelPort;
@Value("${redis.cluster.clusterName}")
private String masterName;
@Bean
public JedisPoolConfig jedisPoolConfig(){
JedisPoolConfig jedisPoolConfig= new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(Integer.parseInt(maxActive));
jedisPoolConfig.setMaxIdle(Integer.parseInt(maxIdle));
jedisPoolConfig.setMinIdle(Integer.parseInt(minIdle));
jedisPoolConfig.setTestOnBorrow(false);
jedisPoolConfig.setTestOnReturn(false);
jedisPoolConfig.setTestWhileIdle(true);
return jedisPoolConfig;
}
@Bean
public JedisSentinelPool jedisSentinelPool(JedisPoolConfig jedisPoolConfig){
Set sentinels= new HashSet();
HostAndPort sentinelHostAndPort= new HostAndPort(sentinelHost, Integer.parseInt(sentinelPort));
sentinels.add(sentinelHostAndPort.toString());
JedisSentinelPool jedisSentinelPool= new JedisSentinelPool(masterName, sentinels, jedisPoolConfig);
return jedisSentinelPool;
}
}
總結(jié):這個(gè)方法適合存儲(chǔ)對(duì)象,因?yàn)橹攸c(diǎn)是redis保存數(shù)據(jù)時(shí)序列化與獲取數(shù)據(jù)反序列化颠焦。