java高并发实际处理简介

java高并发简介,这里我讲点干货,带水分的都除掉啊。如果喜欢,请点赞,给予编写动力。

java高并发实际处理简介

秒杀锁定图

平时项目中,如果多个客户同时需要修改或者审批同一个业务数据的时候,这个时候我们需要考虑脏数据和数据不可重复读问题。脏数据和数据不可重复读问题是java并发的一种业务场景。

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

不可重复读:指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。

处理有两种方式:一种是代码层次上的,如java中的同步锁,典型的就是同步关键字synchronized,另外一种就是数据库层次锁,在数据被锁定的情况下,禁止异步修改。java关键字synchronized编写代码层次的锁,似乎有效。但是实际我们在开发及部署项目的时候可能作用不大,因为实际项目不太可能单机部署。如果部署多台或者分布式部署,那么synchronized就不起作用了。所以这里我也不讲了,大家可以去查看其它资料看详情及synchronized用法。我下面详情简介一下数据库层次的锁。

数据库层次锁有两种,一种是悲观锁,一种是乐观锁。

悲观锁:正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自 外部系统的事务处理)修改持保守态度,因此, 在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能 真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系 统不会修改数据)。

一个典型的依赖数据库的悲观锁调用:

select * from emp where name=”Ea” for update

这条 sql 语句锁定了 emp 表中所有符合检索条件( name=”Ea” )的记录。

本次事务提交之前(事务提交时会释放事务过程中的锁),外界无法修改这些记录。

乐观锁:大多是基于数据版本 (Version )记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来 实现。 读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提 交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据 版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。添加版本只是乐观锁的一种方法,乐观锁主要做法就是表添加一个控制版本字段,这个版本字段不一定必须加一,按照大小来判断是非有修改痕迹。

select e.*,e.version from emp e where e.name=”Ea”

查询数据的时候,将版本号取出。在update的时候

update emp e set e.name='Ae',e.version='#uuid' where e.version='取出的version' and e.id='#id'.

如果前面一个客户对数据进行了修改,后面一个客户修改的时候,是修改不成功的。需要刷新页面看到修改后的数据,看到被修改后的数据,再确定是否进行修改。数据库锁都有好处,但是也都有坏处。

悲观锁大多数情况下依 靠数据库的锁机制实现,以保证操作最大程度的独占性。但随之而来的就是数据库性能的大量开销,特别是对长事务而言,这样的开销往往无法承受。悲观锁会一直将表锁住,其他用户操作会一直等待,如果系统出现问题,事物处理过程中,出现bug,很容易出现锁表。导致整个业务瘫痪。因此不建议使用悲观锁。

乐观锁不会出现悲观锁这种情况。但是乐观锁是一种先下手为强的方式。就和我们抢火车票一样,先将火车票锁定,后面再付款。乐观锁对整个系统及客户可能更好一些。

java高并发实际处理简介

实际项目研发过程中,我们还需要考虑提高高并发下访问的效率的手段

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

1、可能是服务器网络带宽不够

2、可能web线程池连接数不够

3、可能数据库连接池查询上不去

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

1. 像第一种情况可以增加网络带宽,DNS域名解析分发多台服务器。

2. 负载均衡,前置代理服务器nginx、apache等等

3. 数据库查询优化,读写分离,分表等等

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

· 尽量使用缓存,包括用户缓存,信息缓存等,多花点内存来做缓存,可以大量减少与数据库的交互,提高性能。

· 用jprofiler等工具找出性能瓶颈,减少额外的开销。

· 优化数据库查询语句,减少直接使用hibernate等工具的直接生成语句(仅耗时较长的查询做优化)。

· 优化数据库结构,多做索引,提高查询效率。

· 统计的功能尽量做缓存,或按每天一统计或定时统计相关报表,避免需要时进行统计的功能。

· 能使用静态页面的地方尽量使用,减少容器的解析(尽量将动态内容生成静态html来显示)。

· 解决以上问题后,使用服务器集群来解决单台的瓶颈问题。

猜你喜欢

转载自blog.csdn.net/weixin_38423249/article/details/80577008