并发

网站的高并发,大流量访问如何解决?

1、HTML页面静态化
访问的频率较高但内容变动较小,使用网站HTML静态化方案来优化访问速度。
优势:

  • 减轻服务器负担。
  • 加快页面打开速度,静态页面无需访问数据库,打开速度较动态页面有明显提高;
  • 很多搜索引擎都会优先收录静态页面,不仅被收录的快,还收录的全,容易被搜 索引擎找到;
  • HTML 静态页面不会受程序相关漏洞的影响,减少攻击 ,提高安全性。

2、图片和应用服务器相分离

将网页上的图片另外使用一个或多个服务器进行存储,将图片放在一个虚拟目录中,网页上的图片都是使用一个url地址指向图片服务器中的图片地址。
优势:
(1)分担 Web 服务器的 I/O 负载-将耗费资源的图片服务分离出来,提高服务器的性能 和稳定性。
(2)能够专门对图片服务器进行优化-为图片服务设置有针对性的缓存方案,减少带宽 成本,提高访问速度。
(3)提高网站的可扩展性-通过增加图片服务器,提高图片吞吐能力。

3、数据库

4、缓存
通过使用缓存,减少与数据库之间的直接交互,提高性能。
5、镜像
一个磁盘上的数据在另一个磁盘上存在一个完全相同的副本,即为镜像。
6、负载均衡
使用负载均衡为一个应用创建一个由多态服务器组成的服务器集群,将并发访问请求分发到多台服务器处理,避免单衣服武器因负载压力过大而响应缓慢,使用户请求有更好的响应延迟特性。
7、并发控制
加锁
8、消息队列

例如:订票系统,某车次只有一张火车票,假定有 1w 个人同 时打开 12306 网站来订票,如何解决并发问题?(可扩展 到任何高并发网站要考虑的并发读写问题)。
不但要保证 1w 个人能同时看到有票(数据的可读性),还要保证最终只能由一个人买到票(数据的排他性)。
使用数据库层面的并发访问控制机制。采用乐观锁即可解决此问题。乐观 锁意思是不锁定表的情况下,利用业务的控制来解决并发问题,这样既保证数 据的并发可读性,又保证保存数据的排他性,保证性能的同时解决了并发带来 的脏数据问题。hibernate 中实现乐观锁。

并发包

并发包中含有的类:

  • ConcurrentHashMap / CopyOnWriteArrayList。
  • 阻塞队列。
  • 同步辅助类。
  • 和线程池相关的类。
  • Lock 接口。
  • 原子类。

CountDownLatch:
它相当于一个计数器。用一个给定的数值初始化 CountDownLatch,之后计数器就从这个值开始倒计数,直到计数值达到零。
CountDownLatch 是通过“共享锁”实现的。
在创建 CountDownLatch 时, 会传递一个 int 类型参数,该参数是“锁计数器”的初始状态,表示该“共享锁” 最 多 能 被 count 个 线 程 同 时 获 取 , 这 个 值 只 能 被 设 置 一 次 , 而 且 CountDownLatch 没有提供任何机制去重新设置这个计数值。主线程必须在启动其他线程后立即调用 await()方法。这样主线程的操作就会在这个方法上阻塞,直到其他线程完成各自的任务。
当某线程调用该 CountDownLatch 对象的 await()方法时,该线程会等待“共享锁”可用时,才能获取“共享锁”进而继续运行。
而“共享锁”可用的条件,就是“锁计数器”的值为 0!而“锁计数器” 的初始值为 count,每当一个线程调用该 CountDownLatch 对象的 countDown() 方法时,才将“锁计数器”-1;通过这种方式,必须有 count 个线程调用 countDown()之后,“锁计数器”才为 0,而前面提到的等待线程才能继续运行!

await函数:
让线程阻塞等待其他线程,直到 CountDownLatch 的计 数值变为 0,才继续执行之后的操作。
countDown函数:
将 CountDownLatch 的计数值减 1,如果计 数达到 0,则释放所有等待的线程。

CyclicBarrier:
循环的屏障,这个类是一个可以重复利用的 屏障类。它允许一组线程相互等待,直到全部到达某个公共屏障点,然后所有 的这组线程再同步往后执行。

CountDownLatch 和 CyclicBarrier 的区别?
(1) CountDownLatch 的作用是允许 1 个线程等待其他线程执行完成之后, 它才执行;
而 CyclicBarrier 则是允许 N 个线程相互等待到某个公共屏障点,然 后这一组线程再同时执行。
(2) CountDownLatch 的计数器的值无法被重置,这个初始值只能被设置一 次,是不能够重用的;CyclicBarrier 是可以重用的。

Semaphore:
可以控制某个资源可被同时访问的个数,通过构造函数设定一定数量的许 可,通过 acquire() 获取一个许可,如果没有就等待,而 release() 释放一个许可。

阻塞队列

是一个支持两个附加操作的队列。这两个附加的操作是: 在队列为空时,获取元素的线程会等待队列变为非空。当队列满时,存储元素的线程会等 待队列可用。
1.ArrayBlockingQueue
由数组支持的有界缓存的阻塞队列,在读写操作上都需要 锁住整个容器,因此吞吐量与一般的实现是相似的,适合于实现“生产者消费者”模式。ArrayBlockingQueue 内部还保存着两个整形变量,分别标识着队列的头部和尾部在数组中 的位置。这个类是线程安全的。生产者和消费者共用一把锁。
2.LinkedBlockingQueue
基于链表的阻塞队列,内部维持着一个数据缓冲队列(该队列由链表构成)。
只有当队列缓冲区达到最大值缓存容量时,才会阻塞生产者线程,直到消费者从队列中消费掉一份数据,生产者线程会 被唤醒,反之对于消费者这端的处理也基于同样的原理。
LinkedBlockingQueue 之所以能够高效的处理并发数据,还因为其对于生产者端和消 费者端分别采用了独立的锁来控制数据同步,这也意味着在高并发的情况下生产者和消费 者可以并行地操作队列中的数据,以此来提高整个队列的并发性能。

两者的区别:
(1)队列大小的初始化方法不同
ArrayBlockingQueue 是有界的,必须指定队列的大小;
LinkedBlockingQueue 是分情况的,指定队列的大小时,就是有界的;不指定队列的大小 时,默认是 Integer.MAX_VALUE,看成无界队列,但当生产速度大于消费速度时候,有可能 会内存溢出。
(2)队列中锁的实现不同
ArrayBlockingQueue 实现的队列中的锁是没有分离的,即生产和消费用的是同一个锁;进 行 put 和 take 操作,共用同一个锁对象。也即是说,put 和 take 无法并行执行!
LinkedBlockingQueue 实现的队列中的锁是分离的,即生产用的是 putLock,消费是 takeLock。也就是说,生成端和消费端各自独立拥有一把锁,避免了读(take)写(put)时互 相竞争锁的情况,可并行执行。
(3)在生产或消费时操作不同
ArrayBlockingQueue 基于数组,在插入或删除元素时,是直接将枚举对象插入或移除的, 不会产生或销毁任何额外的对象实例;
LinkedBlockingQueue 基于链表,在插入或删除元素时,需要把枚举对象转换为 Node<E> 进行插入或移除,会生成一个额外的 Node 对象,这在长时间内需要高效并发地处理大批量数据的系统中,其对于 GC 的影响还是存在一定的区别,会影响性能。
(4)Put()和 take()方法。
Put()方法:把元素加入到阻塞队列中,如果阻塞队列没有空间,则调用此方法的线程被阻塞, 直到有空间的时候再继续。
take()方法:取出排在阻塞队列首位的对象,若阻塞队列为空,则调用此方法的线程被阻塞, 直到有新的对象被加入的时候再继续。

3.PriorityBlockingQueue与PriorityQueue
PriorityBlockingQueue基于数组的无界阻塞队列,按照元素的优先级对元素进行排序,按照优 先级顺序出队,每次出队的元素都是优先级最高的元素。
PriorityQueue队列的元素并不是全部按优先级排序的,但是队头的优先级肯定是最高的。每取一个头元 素时候,都会对剩余的元素做一次调整,这样就能保证每次队头的元素都是优先级最高的元素。
4.DelayQueue
是一个无界阻塞队列,用于放置实现了 Delayed 接口的对象,只有在延迟期 满时才能从中提取元素。该队列的头部是延迟期满后保存时间最长的 Delayed 元素。
DelayQueue 内部使用 PriorityQueue 实现的。DelayQueue 是一个使用 PriorityQueue 实现的 BlockingQueue,优先队列的比较基准值是时间。本质上即:DelayQueue = BlockingQueue +PriorityQueue + Delayed。
5.SynchronousQueue
同步队列是一个不存储元素的队列,它的 size()方法总是返回 0。每个线程的插入操作必须等待另一个线程的移除操作,同样任何一个线程的移除操作都必须等待另一个线程的插入操作。该队列是一个缓存为1的阻塞队列。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值