redis单点缓存数据库操作封装
2017-07-05 17:07
519 查看
redis服务模块封装
redis单节点缓存数据库操作分装类;这篇博客对应上一篇博客CentOS7-源码安装redis单节点。此处,继上次安装好的redis之后,通过Java访问redis,并将redis操作封装成工具类。
包结构
其中:
——测试类:RedisTest
——服务类:RedisService
——工具类:RedisUtil
——配置文件:redis.properties
——配置文件备份:redis.bak
采用架构:Spring MVC
redis所需架包:
其中,被选中的*.src包为源码包,发布的应用中不需要。
说明:项目仅引用redis的所需的包会报一个错,logger日志的所用类会找不到。源码是logger日志这里用的是log4j的包,被整合在SpringMVC架构包中。解决方式可以将log4j对应的包导入,或者将logger的打印信息直接注释,这也不影响redis服务类的使用。
配置文件信息
RedisUtil工具类
RedisService服务类
测试类RedisTest代码就不贴了,有兴趣的自己copy源码测试一波,博主自己在多线程环境下测试过所有服务功能,均可用,如有发现问题,亦可给我留言。
博主的测试环境是:
——redis单节点位置:CentOS7.2-x86-64;
——测试环境:Win7-x86-64,eclipse,jdk8,JMeter;
——测试最大并行线程量:8000;
——已发现并修正的问题:释放jedis资源时,多线程下报错;
另注意,如果redis数据库节点位置与测试所用PC不在统一网络上,需确保两台计算机之间通信稳定。
redis单节点缓存数据库操作分装类;这篇博客对应上一篇博客CentOS7-源码安装redis单节点。此处,继上次安装好的redis之后,通过Java访问redis,并将redis操作封装成工具类。
包结构
其中:
——测试类:RedisTest
——服务类:RedisService
——工具类:RedisUtil
——配置文件:redis.properties
——配置文件备份:redis.bak
采用架构:Spring MVC
redis所需架包:
其中,被选中的*.src包为源码包,发布的应用中不需要。
说明:项目仅引用redis的所需的包会报一个错,logger日志的所用类会找不到。源码是logger日志这里用的是log4j的包,被整合在SpringMVC架构包中。解决方式可以将log4j对应的包导入,或者将logger的打印信息直接注释,这也不影响redis服务类的使用。
配置文件信息
#Redis服务器IP ADDR = 10.0.0.6 #Redis的端口号 PORT = 6379 #访问密码 AUTH = anson #可用连接实例的最大数目,默认值为8; MAX_ACTIVE = 500 #控制一个pool最多有多少个状态为空闲的 MAX_IDLE = 500 #等待可用连接的最大时间,单位毫秒 MAX_WAIT = 10000 TIMEOUT = 10000 #在获取一个jedis实例时,是否提前进行可用性判断 TEST_ON_BORROW = true
RedisUtil工具类
package com.esh.redis; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.Properties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; /** * @author Anson * Copyright by EasyShare 2017 * * All right reserved * * Created on 2017年6月25日 下午4:12:56 * * redis工具类 */ public final class RedisUtil { //Redis服务器IP private static String ADDR; //Redis的端口号 private static int PORT; //访问密码 private static String AUTH; //可用连接实例的最大数目,默认值为8; private static int MAX_ACTIVE; //控制一个pool最多有多少个状态为空闲的,默认值也是8。 private static int MAX_IDLE; //等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。 private static int MAX_WAIT; private static int TIMEOUT; //在获取一个jedis实例时,是否提前进行可用性判断;如果为true,则得到的jedis实例均是可用的; private static boolean TEST_ON_BORROW; private static JedisPool jedisPool = null; private static Logger logger=LoggerFactory.getLogger(RedisUtil.class.getName()); /** * 初始化Redis连接池 */ static { try { //加载参数 loadProperty(); } catch (Exception e) { e.printStackTrace(); } } /** * 加载redis配置参数 */ private final static void loadProperty() { Properties prop=new Properties(); try { prop.load(new FileInputStream(new File(Thread.currentThread().getContextClassLoader().getResource("").getPath()+"redis.properties"))); ADDR=prop.getProperty("ADDR").trim(); PORT=Integer.parseInt(prop.getProperty("PORT").trim()); AUTH=prop.getProperty("AUTH"); MAX_ACTIVE=Integer.parseInt(prop.getProperty("MAX_ACTIVE").trim()); MAX_IDLE=Integer.parseInt(prop.getProperty("MAX_IDLE").trim()); MAX_WAIT=Integer.parseInt(prop.getProperty("MAX_WAIT").trim()); TIMEOUT=Integer.parseInt(prop.getProperty("TIMEOUT").trim()); TEST_ON_BORROW=prop.getProperty("TEST_ON_BORROW").trim().toLowerCase().equals("true"); logger.info("redis参数加载成功," + "参数:ADDR="+ADDR+" PORT="+PORT+" AUTH="+AUTH+ "MAX_ACTIVE="+MAX_ACTIVE+" MAX_IDLE="+MAX_IDLE+" MAX_WAIT="+MAX_WAIT+" TIMEOUT="+TIMEOUT+" TEST_ON_BORROW="+TEST_ON_BORROW); } catch (IOException e) { e.printStackTrace(); } } /** * 创建redis池 */ private final static void initJedisPool() { try { JedisPoolConfig config = new JedisPoolConfig(); config.setMaxTotal(MAX_ACTIVE); config.setMaxIdle(MAX_IDLE); config.setMaxWaitMillis(MAX_WAIT); config.setTestOnBorrow(TEST_ON_BORROW); jedisPool = new JedisPool(config, ADDR, PORT, TIMEOUT, AUTH); // logger.info(jedisPool!=null?"redis池创建成功":"redis池创建失败,位置:"+RedisUtil.class.getName()); logger.info(jedisPool!=null?"redis连接池创建成功":""); }catch(Exception e) { logger.error("第一次尝试创建jedis连接池错误,位置:"+RedisUtil.class.getName()); try { JedisPoolConfig config = new JedisPoolConfig(); config.setMaxIdle(MAX_ACTIVE); config.setMaxIdle(MAX_IDLE); config.setMaxWaitMillis(MAX_WAIT); config.setTestOnBorrow(TEST_ON_BORROW); jedisPool = new JedisPool(config, ADDR, PORT, TIMEOUT, AUTH); logger.info(jedisPool!=null?"redis连接池创建成功":""); }catch(Exception e1) { logger.error("第二次尝试创建jedis连接池错误,位置:"+RedisUtil.class.getName()); } } } /** * 多线程下同步初始化 */ private synchronized static void loadPool() { if(jedisPool==null) { initJedisPool(); } } /** * 同步获取Jedis实例 * @return */ public synchronized static Jedis getJedis(){ if(jedisPool==null) { //未创建连接池是创建连接池 loadPool(); } Jedis jedis=null; try { if (jedisPool != null) { jedis= jedisPool.getResource(); } } catch (Exception e) { logger.info("获取redis对象失败,位置:"+RedisUtil.class.getName()); e.printStackTrace(); } return jedis; } /** * 释放jedis资源 * @param jedis */ public synchronized static void close(final Jedis jedis){ if (jedis!=null) { jedis.close(); } } }
RedisService服务类
package com.esh.redis; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import redis.clients.jedis.Jedis; import redis.clients.jedis.Transaction; /** * @author Anson * Copyright by EasyShare 2017 * * All right reserved * * Created on 2017年6月25日 下午4:12:38 * * redis服务类 */ public class RedisService { private static Logger logger=LoggerFactory.getLogger(RedisService.class.getName()); /** * 通过key值获取redis中的value,获取后释放链接 * @param key * @return * object */ public synchronized static Object get(String key) { Jedis jedis=null; byte[] value=null; Object obj=null; jedis=RedisUtil.getJedis(); value=jedis.get(key.getBytes()); if(value!=null) { obj=deSerialize(value); } RedisUtil.close(jedis); logger.info(obj!=null?"获取缓存成功,":"获取缓存数据失败,位置:"+RedisService.class.getName()); return obj; } /** * 缓存一个对象,key存在则覆盖 * @param key * @param value * @return * boolean */ public synchronized static boolean set(String key, Object obj) { Jedis jedis=null; String code=null; jedis=RedisUtil.getJedis(); code=jedis.set(key.getBytes(), serialize(obj)); RedisUtil.close(jedis); logger.info(code.toLowerCase().equals("ok")?"缓存成功":"数据缓存失败,位置:"+RedisService.class.getName()); return code.toLowerCase().equals("ok"); } /** * 缓存一个键值对,key-value * @param key * @param value * @return * boolean */ public synchronized static boolean set(String key, String value) { Jedis jedis=null; String code=null; jedis=RedisUtil.getJedis(); code=jedis.set(key.getBytes(), serialize(value)); RedisUtil.close(jedis); logger.info(code.toLowerCase().equals("ok")?"缓存成功":"数据缓存失败,位置:"+RedisService.class.getName()); return code.toLowerCase().equals("ok"); } /** * redis批量写入 * 事物操作 * 当前进行的事物操作,若对应的数据被其他进程修改,则该事物将被打断 * @param objects * Map<String, Object> * @return */ public synchronized static boolean tset(Map<String, Object> objects) { Jedis jedis=null; List<Object> result=null; jedis=RedisUtil.getJedis(); Transaction t=null; try { t=jedis.multi(); for(Entry<String, Object> entry:objects.entrySet()) { //监视数据 t.watch(entry.getKey().getBytes()); //保存数据 t.set(entry.getKey().getBytes(), serialize(entry.getValue())); } result=t.exec(); } catch (Exception e) { //回滚操作 t.discard(); logger.error("redis事物存储失败,位置:"+RedisService.class.getName()); } RedisUtil.close(jedis); return result!=null; } /** * 删除key对应的缓存数据 * @param key * @return * boolean */ public synchronized static long del(String ... keys) { Jedis jedis=null; long code=0; jedis=RedisUtil.getJedis(); code=jedis.del(keys); RedisUtil.close(jedis); logger.info(code>1?"删除成功":"缓存数据删除失败,位置:"+RedisService.class.getName()); return code; } /** * 批量删除操作 * @param key * @return */ public synchronized static long delbat(String key) { Jedis jedis=null; long code=0; jedis=RedisUtil.getJedis(); Set<String> keySet=jedis.keys(key+"*"); if(keySet!=null&&keySet.size()>0) { //将获得的keys转换成数组类型 String[] keys=new String[keySet.size()]; keySet.toArray(keys); code=jedis.del(keys); } RedisUtil.close(jedis); return code; } /** * 清空数据库 * @param isClearAll * 是否清空所有数据库 * false-清空当前使用的数据库,默认为0 * @return * true||false */ public synchronized static boolean clear(boolean isClearAll) { Jedis jedis=null; String code=null; jedis=RedisUtil.getJedis(); if(isClearAll) { code=jedis.flushAll(); logger.info(code.toLowerCase().equals("ok")?"清空所有缓存数据库成功":"清空所有缓存数据库失败"); }else { code = jedis.flushDB(); logger.info(code.toLowerCase().equals("ok")?"清空当前缓存数据库清空成功":"清空当前缓存数据库失败"); } RedisUtil.close(jedis); return code.toLowerCase().equals("ok"); } /** * 批量获取操作 * @param key * @return */ public synchronized static List<Object> getbat(String key) { Jedis jedis=null; List<Object> objects=new ArrayList<Object>(); Object object=null; jedis=RedisUtil.getJedis(); Set<String> keySet=jedis.keys(key+"*"); RedisUtil.close(jedis); if(keySet!=null&&keySet.size()>0) { Iterator<String> it=keySet.iterator(); while(it.hasNext()) { String item=it.next(); object=get(item); if(object!=null) { objects.add(object); } } } return objects; } /** * 序列化存储对象 * @param obj * @return */ private synchronized static byte[] serialize(Object obj) { byte[] serialObj=null; ObjectOutputStream oos=null; ByteArrayOutputStream baos=null; try { baos=new ByteArrayOutputStream(); oos=new ObjectOutputStream(baos); oos.writeObject(obj); serialObj=baos.toByteArray(); } catch (IOException e) { e.printStackTrace(); }finally { try { if(baos!=null) { baos.close(); } if(oos!=null) { oos.close(); } } catch (IOException e) { e.printStackTrace(); logger.error("释放序列化资源失败,位置:"+RedisService.class.getName()); } } return serialObj; } /** * 反序列化对象 * @param serialObj * @return */ private synchronized static Object deSerialize(byte[] serialObj) { Object object=null; ObjectInputStream ois=null; ByteArrayInputStream bais=null; try { if(serialObj!=null&&serialObj.length>0) { bais=new ByteArrayInputStream(serialObj); ois=new ObjectInputStream(bais); object=ois.readObject(); } } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); }finally { try { if(bais!=null) { bais.close(); } if(ois!=null) { ois.close(); } } catch (IOException e) { e.printStackTrace(); logger.error("释放反序列化资源失败,位置:"+RedisService.class.getName()); } } return object; } }
测试类RedisTest代码就不贴了,有兴趣的自己copy源码测试一波,博主自己在多线程环境下测试过所有服务功能,均可用,如有发现问题,亦可给我留言。
博主的测试环境是:
——redis单节点位置:CentOS7.2-x86-64;
——测试环境:Win7-x86-64,eclipse,jdk8,JMeter;
——测试最大并行线程量:8000;
——已发现并修正的问题:释放jedis资源时,多线程下报错;
另注意,如果redis数据库节点位置与测试所用PC不在统一网络上,需确保两台计算机之间通信稳定。
相关文章推荐
- iOS数据库离线缓存思路和网络层封装——数据缓存操作封装
- 数据库缓存-Redis 部署与基本操作
- redis实时缓存数据库简单操作命令
- PHP中对数据库操作的封装
- 数据库操作封装--ExecuteNonQuery
- 使用组件封装数据库操作(二)
- 我封装的ADO.NET对数据库操作经典类
- 使用组件封装数据库操作(一)
- 数据库操作的封装类 Access\FoxPro\SQLServer\Oracle
- 封装的ADO.NET对数据库操作经典类
- 一个封装了数据库大部分操作的JavaBean
- JAVA:数据库操作封装(1)
- PHP中对数据库操作的封装
- JAVA:数据库操作封装(2)
- PHP中对数据库操作的封装
- 数据库操作封装--SqlDataAdapter.fill
- JAVA:数据库操作封装
- 将数据库操作封装到Javabean
- C#中一个操作数据库的类的封装,以前写的,被同学改过,很不完善
- 数据库操作封装--执行事务