`
jinnianshilongnian
  • 浏览: 21513528 次
  • 性别: Icon_minigender_1
博客专栏
5c8dac6a-21dc-3466-8abb-057664ab39c7
跟我学spring3
浏览量:2420435
D659df3e-4ad7-3b12-8b9a-1e94abd75ac3
Spring杂谈
浏览量:3010209
43989fe4-8b6b-3109-aaec-379d27dd4090
跟开涛学SpringMVC...
浏览量:5640557
1df97887-a9e1-3328-b6da-091f51f886a1
Servlet3.1规范翻...
浏览量:260217
4f347843-a078-36c1-977f-797c7fc123fc
springmvc杂谈
浏览量:1597924
22722232-95c1-34f2-b8e1-d059493d3d98
hibernate杂谈
浏览量:250367
45b32b6f-7468-3077-be40-00a5853c9a48
跟我学Shiro
浏览量:5860533
Group-logo
跟我学Nginx+Lua开...
浏览量:702863
5041f67a-12b2-30ba-814d-b55f466529d5
亿级流量网站架构核心技术
浏览量:785723
社区版块
存档分类
最新评论

聊聊高并发之隔离术

阅读更多

扫一扫,关注我的公众号 

 

我的新书 购买地址

 

隔离是指将系统或资源分割开,系统隔离是为了在系统发生故障时能限定传播范围和影响范围,即发生故障后不会出现滚雪球效应,从而保证只有出问题的服务不可用,其他服务还是可用的;而资源隔离有脏数据隔离、通过隔离后减少资源竞争提升性能等。我遇到的比较多的隔离手段有线程隔离、进程隔离、集群隔离、机房隔离、读写隔离、动静隔离、爬虫隔离等。而出现系统问题时可以考虑负载均衡路由、自动/手动切换分组或者降级等手段来提升可用性。

 

线程隔离

线程隔离主要有线程池隔离,在实际使用时我们会把请求分类,然后交给不同的线程池处理,当一种业务的请求处理发生问题时,不会将故障扩散到其他线程池,从而保证其他服务可用。



我们会根据服务等级划分两个线程池,以下是池的抽象:

<bean id="zeroLevelAsyncContext" class="com.jd.noah.base.web.DynamicAsyncContext" destroy-method="stop">
<property name="asyncTimeoutInSeconds" value="${zero.level.request.async.timeout.seconds}"/>
<property name="poolSize" value="${zero.level.request.async.pool.size}"/>
<property name="keepAliveTimeInSeconds" value="${zero.level.request.async.keepalive.seconds}"/>
<property name="queueCapacity" value="${zero.level.request.async.queue.capacity}"/>
</bean>
<bean id="oneLevelAsyncContext" class="com.jd.noah.base.web.DynamicAsyncContext" destroy-method="stop">
<property name="asyncTimeoutInSeconds" value="${one.level.request.async.timeout.seconds}"/>
<property name="poolSize" value="${one.level.request.async.pool.size}"/>
<property name="keepAliveTimeInSeconds" value="${one.level.request.async.keepalive.seconds}"/>
<property name="queueCapacity" value="${one.level.request.async.queue.capacity}"/>
</bean>

 

进程隔离

在公司发展初期,一般是先进行从0到1,不会一上来就进行系统的拆分,这样就会开发出一些比较大而全的系统,系统中的一个模块/功能出现问题,整个系统就不可用了。首先想到的解决方案是通过部署多个实例,然后通过负载均衡进行路由转发,但是这种情况无法避免某个模块因BUG而出现如OOM导致整个系统不可用的风险。因此此种方案只是一个过渡,较好的解决方案是通过将系统拆分为多个子系统来实现物理隔离。通过进程隔离使得某一个子系统出现问题不会影响到其他子系统。


  

集群隔离

随着系统的发展,单实例服务无法满足需求了,此时需要服务化技术,通过部署多个服务,形成服务集群来提升系统容量,如下图所示



随着调用方的增多,当秒杀服务被刷会影响到其他服务的稳定性,此时应该考虑为秒杀提供单独的服务集群,即为服务分组,从而当某一个分组出现问题不会影响到其他分组,从而实现了故障隔离,如下图所示

 
 比如注册生产者时提供分组名:


<jsf:provider id="myService" interface="com.jd.MyService" alias="${分组名}" ref="myServiceImpl"/>

消费时使用相关的分组名即可:

<jsf:consumer id="myService" interface="com.jd.MyService" alias="${分组名}"/>

 

机房隔离

随着对系统可用性的要求,会进行多机房部署,每个机房的服务都有自己的服务分组,本机房的服务应该只调用本机房服务,不进行跨机房调用;其中一个机房服务发生问题时可以通过DNS/负载均衡将请求全部切到另一个机房;或者考虑服务能自动重试其他机房的服务从而提升系统可用性。
 

 

一种办法是根据IP(不同机房IP段不一样)自动分组,还一种较灵活的办法是通过在分组名中加上机房名解决:

<jsf:provider id="myService" interface="com.jd.MyService" alias="${分组名}-${机房}" ref="myServiceImpl"/>
<jsf:consumer id="myService" interface="com.jd.MyService" alias="${分组名}-${机房}"/>

 

读写隔离

如下图所示,通过主从模式将读和写集群分离,读服务只从从Redis集群获取数据,当主Redis集群出现问题时,从Redis集群还是可用的,从而不影响用户访问;而当从Redis集群出现问题时可以进行其他集群的重试。



 

--先读取从
status, resp = slave_get(key)
if status == STATUS_OK then
   return status, value
end
--如果从获取失败了,从主获取
status, resp = master_get(key)

 

动静隔离

当用户访问如结算页时,如果JS/CSS等静态资源也在结算页系统中时,很可能因为访问量太大导致带宽被打满导致出现不可用。


 

因此应该将动态内容和静态资源分离,一般应该将静态资源放在CDN上,如下图所示


 

爬虫隔离

在实际业务中我们曾经统计过一些页面型应用的爬虫比例,爬虫和正常流量的比例能达到5:1,甚至更高。而一些系统是因为爬虫访问量太大而导致服务不可用;一种解决办法是通过限流解决;还一种解决办法是在负载均衡层面将爬虫路由到单独集群,从而保证正常流量可用,爬虫流量尽量可用。

 

比如最简单的使用Nginx可以这样配置:

 

set $flag 0; 
if ($http_user_agent ~* "spider") {
   set $flag "1";
}
if($flag = "0") {
   //代理到正常集群
}
if ($flag = "1") {
   //代理到爬虫集群
}

 

实际场景我们使用了Openresty,不仅仅对爬虫user-agent过滤,还会过滤一些恶意IP(统计IP访问量,配置阀值),将他们分流到固定分组。还有一种办法是种植Cookie,访问特殊服务前先种植Cookie,访问服务时验证该Cookie,如果没有或者不对可以考虑出验证码或者分流到固定分组。

 

热点隔离

秒杀、抢购属于非常合适的热点例子;对于这种热点是能提前知道的,所以可以将秒杀和抢购做成独立系统或服务进行隔离,从而保证秒杀/抢购流程出现问题不影响主流程。

 

还存在一些热点可能是因为价格或突发事件引起的;对于读热点我使用多级缓存搞定;而写热点我们一般通过缓存+队列模式削峰,可以参考《前端交易型系统设计原则》。

 

资源隔离

最常见的资源如磁盘、CPU、网络;对于宝贵的资源都会存在竞争问题。

 

在《构建需求响应式亿级商品详情页》中我们使用JIMDB数据同步时要dump数据,SSD盘容量用了50%以上,dump到同一块磁盘时遇到了容量不足的问题,我们通过单独挂一块SAS盘来专门同步数据。还有如使用Docker容器时,有的容器写磁盘非常频繁,因此要考虑为不同的容器挂载不同的磁盘。

 

默认CPU的调度策略在一些追求极致性能的场景下可能并不太适合,我们希望通过绑定CPU到特定进程来提升性能。如我们一台机器会启动很多个Redis实例,通过将CPU通过taskset绑定到Redis实例上可以提升一些性能;还有Nginx提供了worker_processes和worker_cpu_affinity来绑定CPU。还有如系统网络应用比较繁忙的话,可以考虑绑定网卡IRQ到指定的CPU来提升系统处理中断的能力,从而提升性能。

 

还有如大数据计算集群、数据库集群应该和应用集群隔离到不同的机架,并尽量隔离网络;因为大数据计算或数据库同步时时会有比较大的网络带宽,可能拥塞网络导致应用响应慢。

 

还有一些其他类似的隔离术,如环境隔离(测试环境、预发布环境/灰度环境、正式环境)、压测隔离(真实数据、压测数据隔离)、ABTest(为不同的用户提供不同版本的服务)、缓存隔离(有些系统混用缓存,而有些系统会扔大字节值到如Redis,造成Redis慢查询)、查询隔离(简单、批量、复杂条件查询分别路由到不同的集群)等。通过隔离后可以将风险降低到最低、性能提升至最优。

 

相关阅读

聊聊高并发系统之限流特技-1

聊聊高并发系统之限流特技-2

聊聊高并发系统之降级特技

聊聊高并发系统之HTTP缓存

聊聊高并发系统之队列术

 

前端交易型系统设计原则

构建亿级前端读服务

构建需求响应式亿级商品详情页

京东商品详情页服务闭环实践

商品详情页系统的Servlet3异步化实践

 

 

 

  • 大小: 27.1 KB
  • 大小: 11.8 KB
  • 大小: 9.4 KB
  • 大小: 11.4 KB
  • 大小: 7.1 KB
  • 大小: 10.2 KB
  • 大小: 5.2 KB
  • 大小: 5.6 KB
  • 大小: 7 KB
0
0
分享到:
评论
2 楼 valiant025 2017-10-31  
推荐一个企业分布式服务架构:http://minglisoft.cn/technology
1 楼 zskangs1126 2016-09-22  
  

相关推荐

    聊聊高并发高可用那些事(Kafka、Redis、MySQL)

    MySQL是世界上最流行的开源关系型数据库管理系统之一,其设计目标是处理大量数据,同时提供高并发和高可用性。以下是一些关键知识点: 1. **SQL语句执行流程**:当提交一个SQL语句时,MySQL会经历解析、预处理、...

    王概凯聊聊架构

    3. **分布式系统**:面对高并发和大数据量的挑战,分布式系统设计是必要的。包括负载均衡、分布式数据库、消息队列等技术,它们能帮助提升系统的处理能力和稳定性。 4. **容错与弹性**:在设计架构时,必须考虑到...

    《聊聊架构》

    5. **分布式架构**:在处理高并发和大数据量时,分布式架构成为必然选择。它通过负载均衡、缓存策略、分布式数据库等手段,提升系统的处理能力和容错能力。 6. **容器化与Docker**:Docker提供了一种标准化的打包...

    聊聊MySQL事务的特性和隔离级别

    - 可串行化(Serializable):最严格的隔离级别,通过锁定事务,防止脏读、不可重复读和幻读,但可能导致较高的并发性能损失。 4. 持久性(Durability):一旦事务提交,其对数据库的更改将永久保存,即使系统故障...

    聊聊锁的那些事

    操作系统会为每个进程分配独立的地址空间,以实现内存隔离,保护进程不被其他进程干扰。而线程则共享进程的地址空间,因此线程间的同步更为复杂。 接下来,我们讨论线程和进程的实现原理。进程是一个具有一定独立...

    聊聊数据库中的那些锁.docx

    聊数据库中的那些锁主要涉及数据库事务的ACID属性和锁定机制,这是数据库管理系统中确保数据一致性、并发控制和事务安全的重要概念。 **ACID属性** 1. **原子性(Atomicity)**:原子性保证了事务的不可分割性,一个...

    聊聊分布式事务,再说说解决方案1

    此外,还要考虑事务的隔离级别,如读未提交、读已提交、可重复读和串行化,以及对应的并发控制策略,如锁机制和乐观锁。 在应对分布式事务时,CAP理论为我们提供了指导,但具体实施需要根据业务需求和系统特点灵活...

    聊聊微服务架构及分布式解决方案.docx

    3. **隔离性(Isolation)**:多个事务并发执行时,每个事务都感觉不到其他事务的存在。 4. **持久性(Durability)**:一旦事务完成,它对数据的更改就是永久的,即使系统发生故障也不会丢失。 #### 三、分布式事务...

    聊聊MySQL中的存储引擎

    根据实际业务需求,如需要高并发、事务处理、数据安全等,通常会选择InnoDB;而对于读取密集型且对事务无特殊要求的场景,MyISAM可能是更好的选择。了解和掌握各种存储引擎的特性,对于优化数据库性能和设计高效的...

    亿级流量电商详情页系统实战-缓存架构+高可用服务架构+微服务架构

    讲解一个真实的、复杂的大型企业级亿级高并发项目,是java架构实战课程。 通过本套课程的学习,可以积累大量架构设计经验,迈入架构师行列。 课程特色: 1、完整的大型电商详情页系统架构:不再只是关注电商详情页...

    在linux下开发的聊天系统,公聊,私聊,多线程

    5. **多线程**:多线程编程在聊天系统中至关重要,它可以提高并发性能,让程序能同时处理多个任务。例如,服务器端可能有一个线程监听新的连接,其他线程处理已连接的客户端请求;客户端也可能有一个线程接收消息,...

    聊一聊MyISAM和InnoDB的区别

    这使得MyISAM在高并发的读写环境中性能下降,尤其是当有大量的查询和修改操作时。 与之相比,InnoDB是现在MySQL的默认存储引擎,它支持事务处理,提供了ACID(原子性、一致性、隔离性、持久性)特性,这对于需要...

    聊一聊在ADG环境下“写”堵塞“读”的案例.docx

    总之,虽然Oracle通常能够很好地隔离读写操作,但在这个案例中,由于ADG环境下的实时redo应用和特定的并发情况,写操作确实导致了读操作的阻塞。通过对问题的深入分析和适当的调整,可以有效地解决这种异常情况,...

    combined-test.zip

    4. **性能测试**:对于高并发场景,测试密码接口处理速度和资源消耗,确保在大量请求下仍能正常运行。 5. **安全性审计**:通过渗透测试来检查接口是否存在漏洞,如SQL注入、跨站脚本攻击等。 接下来,我们聊聊...

    最新Java面试题视频网盘,Java面试题84集、java面试专属及面试必问课程

    面试题包含了不同技术层面的面试问题,同时也能对一些没有面试开发经验的小白给予不可估量的包装, 让你的薪水绝对翻倍, 本人亲试有效.Java面试题84集、java面试专属及面试必问课程...└─面试必问-聊聊哈希算法与HashMap

    MyQQ最新版(Java版高仿QQ聊天即时通软件)带mysql数据库

    MySQL的ACID(原子性、一致性、隔离性、持久性)特性确保了数据的一致性和完整性,即使在并发访问的情况下也能保证数据的准确无误。 在Java技术栈中,MyQQ可能采用了Spring Boot框架来构建服务,利用MyBatis或者JPA...

    数据库常见面试题

    - **串行化(Serializable)**:最高的隔离级别,通过锁定所有涉及的行来确保事务顺序执行,避免所有并发问题,但性能较差。 #### 3、MySQL中`varchar`与`char`的区别以及`varchar(50)`中的50代表的涵义? - **`...

    JAVA技术面试题

    - **隔离性**(Isolation):并发执行的事务之间不能互相干扰。 - **持久性**(Durability):一旦事务提交,其结果就是永久性的。 - **回答技巧**:除了解释事务的定义和特性外,还可以简单提及事务在实际开发中...

Global site tag (gtag.js) - Google Analytics