• Java高并发秒杀优化


    只要抛出异常事务就会回滚吗?

    Spring 的事务默认是发生了RunTimeException才会回滚,发生了其他异常不会回滚

    不是所有的方法都需要事务,如只有一条修改操作、只读操作

    Service层中的抛出异常是为了让Spring能够回滚,Controller层中捕获异常是为了将异常转换为对应的json供前台使用。

    return "detail";  //我认为是没有意义的,只是一个字符串而已

    优化总结

    • 前端控制

    暴露接口,按钮防重复(点击一次按钮后就变成灰色,禁止重复点击按钮)

    • 动静态数据分离

    CDN缓存,后端缓存

    • 事务竞争优化

    减少事务行级锁的持有时间


    Redis属于NoSQL,即非关系型数据库,它是key-value型数据库,是直接在内存中进行存取数据的,所以有着很高的性能。
    利用Redis可以减轻MySQL服务器的压力,减少了跟数据库服务器的通信次数。秒杀的瓶颈就在于跟数据库服务器的通信速度(MySQL本身的主键查询非常快)
    Redis有很多客户端,我们的项目是用Java语言写的,自然选择对应Java语言的客户端,而官网最推荐我们的Java客户端是Jedis,在pom.xml里配置了Jedis依赖就可以使用它了,记得要先开启Redis的服务器,Jedis才能连接到服务器。
    由于Jedis并没有实现内部序列化操作,而Java内置的序列化机制性能又不高,我们是一个秒杀系统,需要考虑高并发优化,在这里我们采用开源社区提供的更高性能的自定义序列化工具protostuff。
    使用Redis优化地址暴露接口
    原本查询秒杀商品时是通过主键直接去数据库查询的,选择将数据缓存在Redis,在查询秒杀商品时先去Redis缓存中查询,以此降低数据库的压力。如果在缓存中查询不到数据再去数据库中查询,再将查询到的数据放入Redis缓存中,这样下次就可以直接去缓存中直接查询到。
     

    第一:通过Jedis储存对象的方式有大概三种

    1. 本项目采用的方式:将对象序列化成byte字节,最终存byte字节;
    2. 对象转hashmap,也就是你想表达的hash的形式,最终存map;
    3. 对象转json,最终存json,其实也就是字符串

    3. 秒杀操作——并发优化

    3.1 简单优化

    为什么要先insert再update
    首先是在更新操作的时候给行加锁,插入并不会加锁,如果更新操作在前,那么就需要执行完更新和插入以后事务提交或回滚才释放锁。而如果插入在前,更新在后,那么只有在更新时才会加行锁,之后在更新完以后事务提交或回滚释放锁。
    在这里,插入是可以并行的,而更新由于会加行级锁是串行的。
    也就是说是更新在前加锁和释放锁之间两次的网络延迟和GC,如果插入在前则加锁和释放锁之间只有一次的网络延迟和GC,也就是减少的持有锁的时间。
    这里先insert并不是忽略了库存不足的情况,而是因为insert和update是在同一个事务里,光是insert并不一定会提交,只有在update成功才会提交,所以并不会造成过量插入秒杀成功记录。
     
  • 相关阅读:
    [CLR via C#]5.2 引用类型和值类型
    Yii easyWechat 开发的时候报错:cURL error 60: SSL certificate problem: unable to get local issuer certificat
    前端浏览器自动刷新神器:Browsersync
    phpStudy 切换版本后没有权限的问题
    最全的CSS浏览器兼容问题
    (转)详解JS位置、宽高属性之一:offset系列
    js 跨域问题
    移动端IOS 固定下方的输入框,点击输入框位置会变的修复
    ie8网页时调用特定的css文件
    Bootstrap如何禁止响应式布局 不适配
  • 原文地址:https://www.cnblogs.com/hcw110/p/11119297.html
Copyright © 2020-2023  润新知