一:前端优化

  1. 暴露接口,按钮防重复(点击一次按钮后就变成禁用,禁止重复提交)
  2. 采用CDN存储静态化的页面和一些静态资源(css,js等)

二:Redis后端缓存优化

  1. Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库。
  2. Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
  3. 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
  4. 原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。
  5. 利用Redis可以减轻MySQL服务器的压力,减少了跟数据库服务器的通信次数。

2.1 Redis服务端下载以及安装

详细步骤参考:Redis服务端安装教程

注:以下pom.xml为Maven项目配置文件,若非Maven项目,百度相应名称包导入即可。

2.2 在pom.xml中配置Redis客户端

      <!-- redis客户端:Jedis -->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.7.3</version>
        </dependency>

由于Jedis并没有实现内部序列化操作,而Java内置的序列化机制性能又不高,我们需要考虑高并发优化,在这里我们采用开源社区提供的更高性能的自定义序列化工具protostuff。

2.3 在pom.xml中配置protostuff依赖

        <!-- protostuff序列化依赖 -->
        <dependency>
            <groupId>com.dyuproject.protostuff</groupId>
            <artifactId>protostuff-core</artifactId>
            <version>1.0.8</version>
        </dependency>
        <dependency>
            <groupId>com.dyuproject.protostuff</groupId>
            <artifactId>protostuff-runtime</artifactId>
            <version>1.0.8</version>
        </dependency>

2.4 使用Redis优化数据库访问

  1. 流程:先去Redis缓存中查询,以此降低数据库的压力。如果在缓存中查询不到数据再去数据库中查询,再将查询到的数据放入Redis缓存中,这样下次就可以直接去缓存中直接查询到。
  2. 推荐:新建dao.cache包,实现RedisDao类。例子中缓存实体类名为Seckill.class。例子:
  3. 使用protostuff序列化工具时,被序列化的对象必须是pojo对象(具备setter/getter)
import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtostuffIOUtil;
import com.dyuproject.protostuff.runtime.RuntimeSchema;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
/*
 *  Redis可以近似理解为Map<Key,Value>对象
 */
public class RedisDao {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private final JedisPool jedisPool;

    public RedisDao(String ip, int port) {
        jedisPool = new JedisPool(ip, port);
    }

    private RuntimeSchema<Seckill> schema = RuntimeSchema.createFrom(Seckill.class);

    public Seckill getSeckill(long seckillId) {
        // redis操作逻辑
        try {
            Jedis jedis = jedisPool.getResource();
            try {
                String key = "seckill:" + seckillId;
                // 并没有实现内部序列化操作
                // get-> byte[] -> 反序列化 ->Object(Seckill)
                // 采用自定义序列化
                // protostuff : pojo.
                byte[] bytes = jedis.get(key.getBytes());//根据Key获取Value
                // 缓存中获取到bytes
                if (bytes != null) {
                    // 空对象
                    Seckill seckill = schema.newMessage();
                    ProtostuffIOUtil.mergeFrom(bytes, seckill, schema);
                    // seckill 被反序列化
                    return seckill;
                }
            } finally {
                jedis.close();
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    public String putSeckill(Seckill seckill) {
        // set Object(Seckill) -> 序列化 -> byte[]
        try {
            Jedis jedis = jedisPool.getResource();
            try {
                String key = "seckill:" + seckill.getSeckillId();//保存Value的Key
                byte[] bytes = ProtostuffIOUtil.toByteArray(seckill, schema,
                        LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE));
                // 超时缓存
                int timeout = 60 * 60;// 1小时
                String result = jedis.setex(key.getBytes(), timeout, bytes);
                return result;
            } finally {
                jedis.close();
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }

        return null;
    }

}
  1. 在使用该RedisDao对象时,需要传入Ip地址和端口。
  2. new RedisDao("localhost","6379");
  3. 若使用Spring ICO容器,需配置:
<!--redisDao -->
<bean id="redisDao" class="换成你的包dao.cache.RedisDao">
    <constructor-arg index="0" value="localhost" />
    <constructor-arg index="1" value="6379" />
</bean>
  • 测试Demo:
        Seckill seckill = redisDao.getSeckill(id);
        if (seckill == null) {
            seckill = seckillDao.queryById(id);
            if (seckill != null) {
                String result = redisDao.putSeckill(seckill);
                System.out.pritln(result);
                seckill = redisDao.getSeckill(id);
                System.out.pritln(result);
            }
        }

Java系统高并发之Redis后端缓存优化的更多相关文章

  1. java系统高并发解决方案-转

    转载博客地址:http://blog.csdn.net/zxl333/article/details/8685157 一个小型的网站,比如个人网站,可以使用最简单的html静态页面就实现了,配合一些图 ...

  2. java系统高并发解决方案(转载)

    转载博客地址:http://blog.csdn.net/zxl333/article/details/8454319 转载博客地址:http://blog.csdn.net/zxl333/articl ...

  3. java系统高并发解决方案(转载收藏)

    一个小型的网站,比如个人网站,可以使用最简单的html静态页面就实现了,配合一些图片达到美化效果,所有的页面均存放在一个目录下,这样的网站对系统架构.性能的要求都很简单,随着互联网业务的不断丰富,网站 ...

  4. SSM框架学习之高并发秒杀业务--笔记5-- 并发优化

    前几节终于实现了这个高并发秒杀业务,现在问题是如何优化这个业务使其能扛住一定程度的并发量. 一. 优化分析 对于整个业务来说,首先是分析哪些地方会出现高并发,以及哪些地方会影响到了业务的性能.可能会出 ...

  5. shell脚本清空redis库缓存

    前提: 现在做的一个业务系统,用了redis做缓存. 系统做了缓存,通常在系统正常使用的过程中,可以节省很多系统资源,特别是数据库资源. 但是,在开发.测试或者系统遇到问题的时候,也有很麻烦的事情. ...

  6. JAVA系统架构高并发解决方案 分布式缓存 分布式事务解决方案

    JAVA系统架构高并发解决方案 分布式缓存 分布式事务解决方案

  7. 【高并发架构】Redis缓存高并发之-主从架构

    Redis主从架构 到目前为止,Redis Cluster 能实现很好的性能,但如果只是缓存几个G的数据,那么单机Redis就足够了,但缓存主要用来读的,单机的QPS有一定的极限,一两万QPS一台应该 ...

  8. java高并发之线程池

    Java高并发之线程池详解   线程池优势 在业务场景中, 如果一个对象创建销毁开销比较大, 那么此时建议池化对象进行管理. 例如线程, jdbc连接等等, 在高并发场景中, 如果可以复用之前销毁的对 ...

  9. 【高并发】Redis如何助力高并发秒杀系统,看完这篇我彻底懂了!!

    写在前面 之前,我们在<[高并发]高并发秒杀系统架构解密,不是所有的秒杀都是秒杀!>一文中,详细讲解了高并发秒杀系统的架构设计,其中,我们介绍了可以使用Redis存储秒杀商品的库存数量.很 ...

随机推荐

  1. PVS桌面主镜像配置后,实际用户登录,配置未生效

    1.打开系统属性——高级——用户配置文件下的[设置] 2.打开用户配置文件,可以看到[复制]项灰化 3.使用windwows enable 工具启动上述灰化项,运行附件的exe文件后,任务栏出现下图标 ...

  2. 【爬虫】使用xpath与lxml移除特定标签

    移除标签的两种方式 可以用xpath定位 for bad in html.xpath(".//table"): bad.getparent().remove(bad) 参考:htt ...

  3. View体系第二篇:View滑动

    View滑动的基本思想:当点击事件传到View时,系统记下触摸点的坐标,手指移动时系统记下触摸后的坐标并计算出偏移量,然后根据偏移量修正View坐标. 实现View滑动共有6种方法:layout()方 ...

  4. macOS下MySQL 8.0 安装与配置教程

    一.前言 1.本教程主要内容 适用Homebrew安装MySQL MySQL 8.0 基础适用于配置 MySQL shell管理常用语法示例(用户.权限等) MySQL字符编码配置 MySQL远程访问 ...

  5. JavaScript中,JSON格式的字符串与JSON格式的对象相互转化

    前言:JSON是一个独立于任何语言的数据格式,因此,严格来说,没有“JSON对象”和“JSON字符串”这个说法(然而”菜鸟教程“和”W3school“使用了“JSON对象”和“JSON字符串”这个说法 ...

  6. Spark GraphX快速入门

    GraphX是Spark用于图形并行计算的新组件.在较高的层次上,GraphX通过引入一个新的Graph抽象来扩展Spark RDD:一个定向的多图,其属性附加到每个定点和边.为了支持图计算,Grap ...

  7. 根据class判断

    一.生命不息,代码不止

  8. JavaWeb入门笔记

    Java web笔记 一.HTTP协议 HTTP(超文本传输协议),它是一种主流B/S架构中应用的通信协议.具有以下特点: 1.无状态 服务端不会记录客户端每次提交的请求,服务器一旦相应客户端之后,就 ...

  9. django安装与使用

    django安装与使用 --更新中 安装 我这里采用pip安装 pip install django 创建django工程 创建好的工程,会在当前目录.下 django-admin startproj ...

  10. 6. svg学习笔记-路径

    路径相比于多边形<polygon>元素具有更强绘图能力,<polygon>元素可以绘制任意的多边形,而路径可以绘制任意的轮廓线,是线段,曲线,圆弧的组合形式.svg中可以使用& ...