对于我们开发的网站,如果网站的访问量非常大的话,我们就需要考虑相关的并发访问问题了。而且并发问题也是中高级工程师面试中必问的问题,今天我们就来系统学习一下。

为了更好的理解并发和同步,我们先学习两个重要的概念:同步和异步。

1、同步和异步的区别和联系

所谓同步,可以理解为在执行完一个函数或方法之后,一直等待系统返回值或消息,这时程序是处于阻塞状态的,只有接受到返回值或消息之后才往下执行其他的命令。

所谓异步,执行外函数或方法之后,不必阻塞性地等待返回值或消息,只需要向系统委托一个异步过程,那么当系统接收到返回值或消息时,系统会自动触发委托的异步过程,从而完成一个完整的流程。

同步在一定程度上可以看作是单线程,这个线程请求一个方法之后就等待这个方法给他回复,否则就不往下执行

异步在一定程度上可以看作多线程,请求一个方法之后就不管了,继续执行其他的方法

同步就是一件事,一件事一件事的做。

异步就是,做一件事,不影响做其他的事情。

对于java程序而言,我们会经常听到同步关键字synchronized,假如这个同步的监事对象是类,那么当一个对象访问这个类里面的同步方法的时候,其他的对象也想访问这个同步方法就会进入阻塞状态,只有等前一个对象执行完该同步方法,当前对象才能继续执行该方法,这就是同步。相反,如果方法前没有同步关键字修饰的话,那么不同的对象就可以在同一时间访问同一个方法,这就是异步。再补充一下脏数据和不可重复读的概念。

2、脏数据和不可重复读

脏数据:
脏读就是指,当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务访问并使用了这个数据。因为这个数据还没有提交,那么另外一个事务读到的数据就是脏数据(dirty data),依据脏数据所做的操作可能是不正确的。

不可重复读:
指在数据库访问中,一个事务范围内两个相同的查询却返回了不同的数据。这是由于查询时系统中其它事务修改的提交引起的。一种更容易理解的说法是:在一个事务内,多次读取同一数据。在这个事务还没结束时,另一个事务也访问该数据。那么,在第一个事务的两次读数据之间,由于第二个事务的修改,导致第一个事务两次读到的数据可能不同,因此成为不可重复读,即原始读取不可重复。

3、如何处理并发和同步

今天学习的处理并发和同步问题主要是通过锁机制

锁机制有两个层面:
一种是代码层面上的,如java中的同步锁,典型的就是同步关键字synchronized和lock
http://www.cnblogs.com/xiohao/p/4151408.html
http://www.cnblogs.com/xiohao/p/4151924.html
http://blog.csdn.net/lmb55/article/details/46279155

另一种是数据库层面上的,比较典型的就是悲观锁和乐观锁
有关悲观锁和乐观锁的内容请参看:http://blog.csdn.net/lmb55/article/details/78266667

4、常见java并发同步案例分析

案例一:订票系统案例,某航班只有一张机票,假定有1W个人打开你的网站来订票,问你如何解决并发问题(可扩展到任何高并发网站要考虑的并发读写问题)

问题,1W个人来访问,要求票没出去前必须保证大家都能看到票,不可能一个人在看到票的时候别人就不能看到。但是最后到底谁能抢到,那得要看这个人的“运气”了(网络快慢等)

首先我们容易想到和并发相关的几个方案:

锁同步更多指的是应用程序的层面,多个线程进来,只能一个一个的访问。除了Java中的对象锁,还有另外一个层面—数据库锁。如果是分布式系统,显然只能使用数据库端的锁来实现。

假定我们采用了同步机制或者数据库物理锁机制,如果保证1W个人还能同时看到有票,这显然会牺牲性能,在高并发网站中是不可取的。

由此来看,采用乐观锁即可解决此问题。乐观锁是在不锁表的情况下,利用业务的控制来解决并发问题,这样既保证数据的并发可读性又保证数据的排他性,保证性能的同时也解决了并发带来的脏数据问题

hibernate如何实现乐观锁:

前提:在现有表中增加一个冗余字段,long类型的version版本号。

原理:
1)只有当前版本号>=数据库表的版本号才能提交
2)提价成功后,版本号version++

实现很简单:在orgmapping增加一个属性optimistic-lock=”version”即可,以下是样例片段:

<hibernate-mapping>
<class name="com.stock.ABC" optimistic-lock="version" table="T_Stock" schema="STOCK">
</hibernate-mapping>

案例二:股票交易系统、银行系统,大数据量你是如何考虑的

首先,股票交易系统的行情表,每几秒钟就有一个行情记录产生,一天下来就有(假定行情3s一个)股票数量*20*60*6条记录,一个月下来这个表的记录数量多大?Oracle中一张表的记录数超过100W之后查询性能就很差了,如何保证系统性能?

再比如,中国移动有上亿的用户量,表如何设计?把所有数据存到一张表?

所以,大数据量的系统,必须考虑表拆分(表名不一样,但是结构完全一样),通常用到的有以下几种方式(视情况而定):

1)按业务分。比如手机号的表,我们可以考虑130开头的一个表,131开头的另一个表,以此类推。

2)利用Oracle的表拆分机制做分表

3)如果是交易系统,我们可以考虑按时间轴拆分,当日数据一个表,历史数据弄到其它表。这里历史数据的报表和查询不会影响当日交易。

当然,表拆分后我们的应用要做相应的适配。单纯的orgmapping就得改动了。比如部分业务要通过存储过程等。

此外,我们还要考虑缓存

这里的缓存,指的不仅是hibernate,hibernate本身提供了一级二级缓存。这里的缓存独立于应用,依然是内存的读取。假如我们能减少数据库频繁的访问,那对系统肯定大大有利。比如一个电子商务系统的商品搜索,如果某个关键字的商品经常被搜,那就可以考虑把这部分商品列表存放到缓存(内存)中去,这样不用每次访问数据库,性能大大增加。

简单的缓存我们可以理解为自己做一个HashMap,把经常访问的数据做一个key,value是第一次从数据库搜索出来的值,下次访问就可以从map中读取,而不需要读数据库。目前专业些的有独立缓存框架比如memcached等,可独立部署成一个缓存服务器。

redis实现分布式锁:
http://blog.csdn.net/lmb55/article/details/78235768
Redis实现秒杀:
http://blog.csdn.net/lmb55/article/details/78266905

5、常见的提高高并发下访问效率的手段

首先要了解高并发的瓶颈在哪里?

1)可能是服务器网络带宽不够
2)可能是web线程连接数不够
3)可能是数据库连接查询上不去

根据不同的情况,解决思路也不同

1)像第一种情况可以增加网络带宽,DNS域名解析分发多台服务器。
2)负载均衡,前置代理服务器nginx、apache等等。
3)数据库查询优化,读写分离,分表等等。

最后复制一些在高并发下面常常需要处理的内容:

1)尽量使用缓存,包括用户缓存、信息缓存等,多花点内存来做缓存。可以大量减少与数据库的交互,提高性能。
2)用jprofiler等工具找出性能瓶颈,减少额外开销。
3)优化数据库查询语句,减少直接使用hibernate等工具的直接生成语句(仅耗时较长的查询做优化)
4)优化数据库结构,多做索引,提高查询效率
5)统计的功能尽量做缓存,或按每天统计或者定时统计相关报表,避免需要时进行统计的功能。
6)能使用静态页面的地方尽量使用静态页面,减少容器的解析(尽量将动态内容内容生成静态html显示)。
7)解决以上问题后,使用服务器集群来解决单台的瓶颈问题。

【Java并发编程】java高并发的解决方案(一)相关推荐

  1. 《Java并发编程入门与高并发面试》or 《Java并发编程与高并发解决方案》笔记

    <Java并发编程入门与高并发面试>or <Java并发编程与高并发解决方案>笔记 参考文章: (1)<Java并发编程入门与高并发面试>or <Java并发 ...

  2. Java 高并发_JAVA并发编程与高并发解决方案 JAVA高并发项目实战课程 没有项目经验的朋友不要错过!...

    JAVA并发编程与高并发解决方案 JAVA高并发项目实战课程 没有项目经验的朋友不要错过! 1.JPG (37.82 KB, 下载次数: 0) 2018-12-3 09:40 上传 2.JPG (28 ...

  3. 01 - Java并发编程与高并发解决方案笔记-基础篇

    01 - Java并发编程与高并发解决方案笔记-基础篇 基础篇很重要!很重要!很重要!!!一定要理解和认真思考. 01 - Java并发编程与高并发解决方案笔记-基础篇 1.课程准备 2.并发编程基础 ...

  4. JavaWeb 并发编程 与 高并发解决方案

    在这里写写我学习到和自己所理解的 Java高并发编程和高并发解决方案.现在在各大互联网公司中,随着日益增长的互联网服务需求,高并发处理已经是一个非常常见的问题,在这篇文章里面我们重点讨论两个方面的问题 ...

  5. java并发编程与高并发解决方案

    知识点 线程安全,线程封闭,线程调度,同步容器,并发容器,AQS,J.U.C,等等 高并发解决思路与手段 扩容:水平扩容.垂直扩容 缓存:Redis.Memcache.GuavaCache等 队列:K ...

  6. 高并发编程_高并发编程系列:7大并发容器详解(附面试题和企业编程指南)...

    不知道从什么时候起,在Java编程中,经常听到Java集合类,同步容器.并发容器,高并发编程成为当下程序员需要去了解掌握的技术之一,那么他们有哪些具体分类,以及各自之间的区别和优劣呢? 只有把这些梳理 ...

  7. java高并发解决方案_长文慎入-探索Java并发编程与高并发解决方案

    所有示例代码,请见/下载于 1 基本概念 1.1 并发 同时拥有两个或者多个线程,如果程序在单核处理器上运行多个线程将交替地换入或者换出内存,这些线程是同时"存在"的,每个线程都处 ...

  8. 高并发编程_高并发编程系列:全面剖析Java并发编程之AQS的核心实现

    在并发编程领域,AQS号称是并发同步组件的基石,很多并发同步组件都是基于AQS实现,所以想掌握好高并发编程,你需要掌握好AQS. 本篇主要通过对AQS的实现原理.数据模型.资源共享方式.获取锁的过程, ...

  9. 转:Java并发编程与高并发解决方案(一)

    转: https://blog.csdn.net/m0_37819279/article/details/81154126 首先介绍连接池 1:ExecutorService是Executor直接的扩 ...

  10. Java多线程学习处理高并发问题

    在程序的应用程序中,用户或请求的数量达到一定数量,并且无法避免并发请求.由于对接口的每次调用都必须在返回时终止,因此,如果接口的业务相对复杂,则可能会有多个用户.调用接口时,该用户将冻结. 以下内容将 ...

最新文章

  1. 单片机怎么做定时器矩阵,彻底解决各种定时问题?
  2. 游戏设计艺术(第3版) The Art of Game Design
  3. 脚本自动配置ssh互信
  4. poj 3352 双连通分量
  5. 精确监听AbsListView滚动至底部
  6. oracle 函数索引
  7. while循环打印*菱形
  8. 用AI算法分析光影看到盲点:这项MIT新研究偷学到二娃技能
  9. 数据库练习(1)——建立数据库
  10. paip.mysql 性能测试 报告 home right
  11. phpstudy集成安装环境所需运行库vc9-vc14(32+64位)下载集合
  12. 基于STM32的有方科技(银而达)N58模块与OneNet平台互联
  13. π型滤波频率计算_π型电感滤波电路计算
  14. java中点击按钮读取和写入文件实现登录和注册
  15. vue项目之微信分享
  16. 11位大咖集结!和最专业的人,探讨“由内及外”的未来趋势 | 生辉 · 生命科学大会-1
  17. CSAPP : Arch Lab 解题报告
  18. 香港、澳门通行证网上申请
  19. 判断dataGridView是否重复值
  20. 在飞腾平台安装MySQL数据库_银河麒麟4.0.2(飞腾平台) 安装MySQL数据库

热门文章

  1. 认识flex中的sprite
  2. 写段QTP脚本与大家一起分享
  3. org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc
  4. android 弹出PopupWindow后背景逐渐变暗
  5. C++实现直接插入排序
  6. 结构光三维重建Projector-Camera Calibration投影仪相机标定
  7. 解决 Successfully created project '' on GitHub, but initial push failed: Could not read from remote re
  8. HttpURLConnection根据URL下载图片
  9. 学JS的心路历程-Promise(一)
  10. Function types cannot have argument labels 错误解决方案