一:前端优化

  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. ajax简单登录(踩过的坑)

    登陆页面: <%@ page language="java" contentType="text/html; charset=UTF-8" pageEnc ...

  2. 使用Nginx实现服务器反向代理和负载均衡

    前言 同事总问我Nginx做反向代理负载均衡的问题,因此特意留下一篇扫盲贴! 直接部署服务器的风险 假设,我开发了一个网站,然后买了一台Web服务器和一台数据库服务器,直接部署到公共网络上.如下图,网 ...

  3. java 大文件分割与组装

    不多说,直接上代码 1 import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; im ...

  4. C#-类(九)

    类的定义 类是描述具有相同特征与行为的事物的抽象,类内部包含类的特征和类的行为 类支持继承 类的定义是关键字class为标志 类的格式 访问标识符 class 类名 { 类主体 } 访问标识符:指定了 ...

  5. C#-封装(七)

    封装概念 C#是面向对象的一门语言,面向对象的语言有三大特性:封装.继承.多态.而封装可以实现一个自定义的类,从而定义新的对象 封装是将一个或多个项目集合在一个单元中,这个单元称之为类.这样可以防止对 ...

  6. 移动端 input样式在安卓与ios上不同的解决方案

    input{ -webkit-appearance:none; }

  7. 前后端分离djangorestframework——分页组件

    Pagination 为什么要分页也不用多说了,大家都懂,DRF也自带了分页组件 这次用  前后端分离djangorestframework——序列化与反序列化数据  文章里用到的数据,数据库用的my ...

  8. 关于Box Anemometer的安装配置遇到的几个坑

    Box Anemometer是一个非常不错的MySQL慢查询可视化工具平台,具体就不多详述了,官网是https://github.com/box/Anemometer 最近动自己动手搭了一个,具体搭建 ...

  9. LeetCode算法题-Nim Game(Java实现)

    这是悦乐书的第203次更新,第213篇原创 01 看题和准备 你和你的朋友正在玩下面的Nim游戏:桌子上有一堆石头,每次你轮流去除1到3块石头. 移除最后一块石头的人将成为赢家. 你是第一个取出石块的 ...

  10. 一个tomcat部署多个应用实例

    安装JDK7sudo apt-get install java7-jdk 安装tomcat7 Tomcat7下载地址http://mirror.bjtu.edu.cn/apache/tomcat/to ...