一、引言

本篇博客以redis缓存为主。至于什么是redis缓存?还有没有其它的缓存?哪个缓存的性能会更好?这里就不一一做介绍了!(有兴趣的可以自己去百度一下)

在日常的开发中,我们或多或少(必须)的会用到缓存。为了提高系统性能、提升用户体验度,用户体验是多么的重要;这就要求在软件设计时,不但要注重可靠性、安全性、可扩展性以及可维护性等等的一些指标,更要注重用户的体验,用户体验分很多方面,但是有一点非常重要就是对用户操作的响应一定要快;怎样提高用户访问的响应速度,这就是摆在架构设计中必须要解决的问题;说到提高服务的响应速度就不得不说缓存了;

从系统的层面说,CPU的速度远远高于磁盘IO的速度;所以要想提高响应速度,必须减少磁盘IO的操作,但是有很多信息又是存在数据库当中的,每次查询数据库就是一次IO操作;请求响应时间等于网络响应时间和服务器响应时间;网络我们控制不了,服务器响应时间包括CPU计算时间和磁盘IO时间,其中CPU计算时间这个有硬件资源决定的,我们尽量减少算法的复杂度来减少它,磁盘IO时间,这个时间是非常慢的,应该尽量减少;

当客户端调用某个接口获取信息的时候,执行顺序1、2、3、4;由于信息存放在DB中,所以2、3就有一次磁盘IO操作;这个看似非常简单业务逻辑,但是当你做架构设计的时候往往要考虑最坏的场景,或者当成千上万的用户频繁的调用这个接口应该怎么处理?如果按照上图这样的架构处理,这个看似简单业务的接口会使整个系统变慢,这样用户的请求就会长时间得不到响应;这样的问题怎么解决那,这时候就该缓存登场了;

缓存有很多种、也有很多种缓存策略。这里就不一一就探讨了,毕竟这篇博客是讲关于的工具类!总之一句话,要想提高系统的性能,尽量减少IO的操作,特别是磁盘IO的操作;使用缓存可以有效的避免这种情况;所以在架构设计过程中,涉及到查询数据库的时候,应该考虑一下是不是使用缓存技术来提高系统的性能,并且降低数据库的压力。

二、无知的痛(用get / set方式使用Redis)

在根据某个需求设计业务的时候,比如说购物车:涉及到添加、查询、修改、删除。不说这四个具体实现时候的细节,这不就简单的对数据库增、删、改、查吗?但是,当成千上万的用户频繁访问的时候,简单的事情在高并发的情况下就会变的不简单!这个时候就需要有个东西来代替数据,而且还要比数据库更快,来应对可能出现的高并发!所以我们想到了(redis)缓存,作为一个key / value 存在,很多开发者自然的使用set/get 方式来使用 redis  ,实际上这并不是最优化的使用方法。尤其在未启用VM 情况下,Redis 全部数据需要放入内存,节约内存尤其重要。 假如一个key-value单元需要最小占用512字节,即使只存一个字节也占了512字节(比如set/get,一个key-value对应一条数据)。这时候就有一个设计模式,可以把key复用,几个key-value作为一个大的value,大的value再作为一个value,set存入一个key中。这样同样512字节就会存放10-100倍的容量。 这就是为了节约内存,建议使用hash类型而不是set/get的方式来使用Redis。

三、hash类型方式使用redis -- 指定返回类型

在日常开发中,我们会把业务中的所有特性封装成一个对象,再把这个对象存入到redis缓存中。在使用redis的时候,通常会把redis常用的方法封装成一个工具类。然后我们调用工具类中的方法,把存入的对象传到方法中。通常方法会把对象转换成string存入缓存,需要的时候再把string取出来,然后再转换成对象!大多数的情况就是如此,但是在我实际的开发中传入的是个和业务有关的对象,返给我的却是一个object对象(和业务没有半毛钱关系)。我想要让返回的对象和业务有关,还得强转一下!这返回的是单个对象,如果是个list呢?循环强转吗?那如果是map呢?当然肯定都是能转的,但是这样就增加了实际业务中的代码量!在我看来多一行于业务无关的代码都是罪恶的(纵然它是为了和业务产生关联),我想要的是 我给你存的是啥!返回的就是啥!别整那些没用的......

1.根据key和fieid返回hash中指定存储位置的值,指定返回类型

  1. /**
  2. * 返回hash中指定存储位置的值
  3. * @param key
  4. * @param fieid
  5. * @param obj
  6. * @param <T>
  7. * @return
  8. */
  9. public<T> T hget(String key,String fieid,T obj) {
  10. Jedis jedis = null;
  11. try {
  12. logger.info("hget >> key+fieid:{}",key +"+"+ fieid);
  13. jedis = jedisPool.getResource();
  14. String hget = jedis.hget(key, fieid);
  15. ObjectMapper om = new ObjectMapper();
  16. T t =(T) om.readValue(hget, obj.getClass());
  17. return t;
  18. } catch (Exception e) {
  19. logger.error("Jedis hget 异常: " + e.getMessage());
  20. return null;
  21. } finally {
  22. closeRedis(jedis);
  23. }
  24. }

调用:

  1. //调用hget方法
  2. DemoDTO demoDTO = jedis.hget("key", "fieid", new DemoDTO());

2.hvals()方法,获取hash中value的集合,指定返回的集合类型

  1. /**
  2. * 获取hash中value的集合,指定返回的集合类型
  3. * @param key
  4. * @param obj
  5. * @param <T>
  6. * @return
  7. */
  8. public<T> List<T> hvals(String key,T obj) {
  9. Jedis jedis = null;
  10. try {
  11. logger.info("hvals >> key:{}",key);
  12. jedis = jedisPool.getResource();
  13. List<String> hvals = jedis.hvals(key);
  14. Iterator<String> iterator = hvals.iterator();
  15. List<T> returnList = new ArrayList<>();
  16. ObjectMapper om = new ObjectMapper();
  17. while (iterator.hasNext()) {
  18. String next = iterator.next();
  19. T t =(T) om.readValue(next, obj.getClass());
  20. returnList.add(t);
  21. }
  22. return returnList;
  23. } catch (Exception e) {
  24. logger.error("Jedis hvals fail >> e:{}",e.getMessage());
  25. return null;
  26. } finally {
  27. closeRedis(jedis);
  28. }
  29. }

调用:

  1. //调用hvals方法
  2. List<DemoDTO> demoListDTOS = jedis.hvals("key", new DemoDTO());

3.以Map的形式返回hash中的存储和值,指定map中的value类型

  1. /**
  2. * 以Map的形式返回hash中的存储和值
  3. * @param key
  4. * @param obj
  5. * @param <T>
  6. * @return
  7. */
  8. public<T> Map<String,T> hgetAll(String key,T obj) {
  9. Jedis jedis = null;
  10. try {
  11. logger.info("hget >> key+obj:{}",key+"+"+obj);
  12. jedis = jedisPool.getResource();
  13. Map<String, String> map = jedis.hgetAll(key);
  14. Map<String, T> returnMap = new HashMap<>();
  15. ObjectMapper om = new ObjectMapper();
  16. for (Map.Entry<String, String> e : map.entrySet()) {
  17. T t =(T) om.readValue(e.getValue(), obj.getClass());
  18. returnMap.put(e.getKey(),t);
  19. }
  20. return returnMap;
  21. } catch (Exception e) {
  22. logger.error("Jedis hget fail >> e:{}" + e.getMessage());
  23. return null;
  24. } finally {
  25. closeRedis(jedis);
  26. }
  27. }

调用:

  1. //调用hgetAll方法
  2. Map<String,DemoDTO> stringDemoDTOMap = jedis.hgetAll("key", new DemoDTO());

4.关闭jedis连接,将jedis连接归还redis连接池

  1. /**
  2. * 关闭jedis连接池
  3. * @param jedis
  4. */
  5. private void closeRedis(Jedis jedis) {
  6. if (jedis != null){
  7. try{
  8. jedis.close();
  9. }catch (Exception e){
  10. logger.error("Jedis关闭异常" + e.getMessage());
  11. }
  12. }
  13. }

closeRedis 释放资源 防止达到最大连接数出现异常 如 :maxTotal=300

如果每次获取完redis连接,不归还redis连接池的话,当超过redis的最大连接数。然后redis就雪崩了!注意!注意!!!

四、结尾

其实指定redis返回类型,没什么高大上的!就是用了ObjectMapper类,这个类是Jackson库的主要类。但是,我百度查过网上很多关于redis的连接工具类,发现却没有一个做过这方面的处理!其实这个也不难,在写业务的时候随手就能写出来。我也就是在用redis的时候偶尔蹦出来了这个想法,每都要多那么两三行于业务无关的代码让人非常的抓狂

高效Redis工具类的更多相关文章

  1. 小D课堂 - 零基础入门SpringBoot2.X到实战_第9节 SpringBoot2.x整合Redis实战_40、Redis工具类封装讲解和实战

    笔记 4.Redis工具类封装讲解和实战     简介:高效开发方式 Redis工具类封装讲解和实战         1.常用客户端 https://redisdesktop.com/download ...

  2. Redis操作Hash工具类封装,Redis工具类封装

    Redis操作Hash工具类封装,Redis工具类封装 >>>>>>>>>>>>>>>>>> ...

  3. Redis操作字符串工具类封装,Redis工具类封装

    Redis操作字符串工具类封装,Redis工具类封装 >>>>>>>>>>>>>>>>>>& ...

  4. redis 工具类 单个redis、JedisPool 及多个redis、shardedJedisPool与spring的集成配置

    http://www.cnblogs.com/edisonfeng/p/3571870.html http://javacrazyer.iteye.com/blog/1840161 http://ww ...

  5. SpringBoot整合Redis及Redis工具类撰写

            SpringBoot整合Redis的博客很多,但是很多都不是我想要的结果.因为我只需要整合完成后,可以操作Redis就可以了,并不需要配合缓存相关的注解使用(如@Cacheable). ...

  6. redistemplate优雅地操作redis redis 工具类

    参考:https://www.cnblogs.com/superfj/p/9232482.html redis 工具类 package com.service; import org.springfr ...

  7. java的redis工具类

    package com.mracale.sell.utils; /** * @Auther: Mracale */ import org.springframework.beans.factory.a ...

  8. Redis 工具类

    项目里的Redis 工具类,写下来以备后用 public class RedisConnector { public class RedisParseResult<T> { public ...

  9. Redis 工具类 java 实现的redis 工具类

    最近了解了一下非关系型数据库 redis 会使用简单的命令 在自己本地电脑 使用时必须先启动服务器端 在启动客户端 redis 简介 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内 ...

随机推荐

  1. 用Node.js给邮箱发送邮件

    首先我们需要做的是下载发送邮件的包 cnpm install nodemailer --save 然后写发送邮件的代码,代码如下: 实现原理是:用你的邮箱给其他邮箱发送邮件,所以这里需要填写你的邮箱和 ...

  2. C++ 回调函数的多种用法

    什么是回调函数, 就是以函数指针做参数传递给另一个函数称之为回调函数, 字面意思很简单, 但就这几个字想理解回调函数, 那又很难.因此别就这这字面意思, 只要知道怎么用, 在什么情况下用就行了 什么场 ...

  3. js json字符串与json对象互相转换(最全)

      1.json字符串转json对象 使用场景:通常在取json字符串里具体的值时,会用到. var jsonString = '{"name":"Marydon&quo ...

  4. 解决 Github 图片加载慢的问题

    一.前言 本文主要介绍一种解决 Github 图片加载慢的方法,亲测有效. 笔者博客是使用 Github 作为图床,每次打开博客时的图片加载很慢或者根本加载不出来.这是因为 GitHub 的 CDN ...

  5. 【Linux命令】at、crontab定时任务

    crontab定时任务(周期性) 一.简介 通过crontab命令可以在固定的间隔执行系统指令或shell脚本 二.crontab配置文件: Linux下的任务调度分为两类:系统任务调度和用户任务调度 ...

  6. js 价格 格式化 数字和金额

    方法一: abs = function(val){ //金额转换 分->元 保留2位小数 并每隔3位用逗号分开 1,234.56 var str = (val/100).toFixed(2) + ...

  7. JVM内存溢出分析java.lang.OutOfMemoryError: Java heap space

    JVM内存溢出查询java.lang.OutOfMemoryError: Java heap space查出具体原因分为几个预备步骤 1.在运行java程序是必须设置jvm -XX:+HeapDump ...

  8. 【UOJ#75】【UR #6】智商锁(矩阵树定理,随机)

    [UOJ#75][UR #6]智商锁(矩阵树定理,随机) 题面 UOJ 题解 这种题我哪里做得来啊[惊恐],,, 题解做法:随机\(1000\)个点数为\(12\)的无向图,矩阵树定理算出它的生成树个 ...

  9. 升级GCC

    1. wget http://ftp.gnu.org/gnu/gcc/gcc-4.9.4/gcc-4.9.4.tar.gz 2. tar -zxvf gcc-4.9.4.tar.gz 3. cd gc ...

  10. Winforn中设置ZedGraph多条Y轴时曲线刻度不均匀问题解决

    场景 Winform中实现ZedGraph的多条Y轴(附源码下载): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/1001322 ...