京东技术,www.toutiao.im
本文转载自kaitao.toutiao.im,转载务必声明。
隔离是指将系统或资源分割开,系统隔离是为了在系统发生故障时能限定传播范围和影响范围,即发生故障后不会出现滚雪球效应,从而保证只有出问题的服务不可用,其他服务还是可用的;而资源隔离有脏数据隔离、通过隔离后减少资源竞争提升性能等。我遇到的比较多的隔离手段有线程隔离、进程隔离、集群隔离、机房隔离、读写隔离、动静隔离、爬虫隔离等。而出现系统问题时可以考虑负载均衡路由、自动/手动切换分组或者降级等手段来提升可用性。
线程隔离
线程隔离主要有线程池隔离,在实际使用时我们会把请求分类,然后交给不同的线程池处理,当一种业务的请求处理发生问题时,不会将故障扩散到其他线程池,从而保证其他服务可用。
我们会根据服务等级划分两个线程池,以下是池的抽象:
<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慢查询)、查询隔离(简单、批量、复杂条件查询分别路由到不同的集群)等。通过隔离后可以将风险降低到最低、性能提升至最优。
相关推荐
3 隔离术 43 3.1 线程隔离 43 3.2 进程隔离 45 3.3 集群隔离 45 3.4 机房隔离 46 3.5 读写隔离 47 3.6 动静隔离 48 3.7 爬虫隔离 49 3.8 热点隔离 50 3.9 资源隔离 50 3.10 使用Hystrix实现隔离 51 3.10.1 Hystrix...
小儿肺叶切除术是治疗某些特定肺部疾病的手术方式,包括叶内型隔离肺和先天性肺气道畸形等情况。小儿患者的胸腔空间相对狭小,解剖结构细密,对手术技术和护理配合提出了更高的要求。通过机器人辅助胸腔镜,可以有效...
手术过程中,医生会在显微镜下找到压迫神经的血管,然后在两者之间插入一种隔离材料,如Teflon垫片,以减轻压力,从而缓解疼痛。MVD的优点在于可以提供长期的疼痛缓解,复发率相对较低,且保留了神经功能。然而,...
[高并发的隔离术] () 2016.09.09 2016.09.08 2016.09.06 2016.09.02 2016.09.01 2016.08.31 2016.08.30 2016.08.29 2016.08.26 2016.08.25 2016.08.24 2016.08.23 2016.08.22 2016.08.19 2016.08.18 2016.08.17 2016...
[高并发的隔离术] () 2018.09.01 2018.09.08 2018.09.06 2018.09.02 2018.09.01 2018.08.31 2018.08.30 2018.08.29 2018.08.26 2018.08.25 2018.08.24 2018.08.23 2018.08.22 2018.08.19 2018.08.18 2018.08.17 2018...
事务处理是数据库操作的基础,书中会详细解释ACID属性(原子性、一致性、隔离性和持久性),以及如何正确地提交和回滚事务,确保数据的一致性和完整性。并发控制是多用户环境下必须面对的问题,Oracle提供了行级锁定...
- **NoSQL数据库**:通常适用于大数据、高并发和实时分析场景,提供水平扩展能力,支持大数据量和复杂数据结构,但可能牺牲部分事务一致性。 **3. 炼金术数据库的特点** - **灵活性**:支持多种数据模型,可以灵活...
2. 白内障超声乳化术:这是现代白内障手术的主要方法,具有手术适应症广泛、术后视力恢复快、减少并发症如脉络膜渗出和出血、减少角膜散光等优点。超声乳化的技术难度相对较高,但效果显著,可以显著改善患者视力。 ...
4. **肠内营养并发症**:肠内营养主要的代谢性并发症是高血糖,因为持续的肠内营养可能导致糖代谢紊乱。 5. **肾功能损害**:急性肾小管功能损害时表现为尿少,且尿钠大于40mmol/L,这表明肾脏重吸收钠的能力受损。...
通常采用的穿刺体位是侧卧位,因为这样可以减少并发症的风险,并提供更好的手术视野。 2. 脑挫裂伤:脑挫裂伤是指脑组织受到外力撞击后出现的损伤,常表现为低密度水肿区域内的高密度出血灶,伴有明显的占位效应和...
15. 心肺复苏术顺序:心肺复苏术的正确顺序是开放气道、胸外按压、人工呼吸,错误的操作顺序可能会延误急救。 16. 健康教育的着眼点:健康教育不仅关注个人获取卫生保健知识,更重视改变个人行为和提高健康素养。 ...
近年来,随着医学技术的进步,尤其是诊断、手术、麻醉、体外循环和围术期监护技术的显著提升,儿童先心病的术后并发症和死亡率已大幅度降低。手术治疗的年龄界限也在不断下移,越来越多的婴幼儿和新生儿得以接受此类...
4. 肠内营养的主要代谢并发症是高血糖,需要监测并调整营养液的输入速度和成分。 5. 急性肾小管功能损害时,尿少且尿钠大于40mmol/L是其典型表现。 6. 强酸、强碱烧伤不会立即出现水泡,而沸水、火焰造成的烧伤通常...
19. **大面积烧伤病人的隔离**:大面积烧伤患者应实施保护性隔离,以防止感染。 20. **病人沐浴注意事项**:水温过高可能导致病人眩晕,应避免。 21. **压疮形成原因**:压疮最主要的原因是局部组织长期受压。 22...
首先,双腔气管插管的适应证主要包括肺部手术、支气管胸膜瘘、气管食管瘘、肺叶或全肺切除术、气管或支气管手术、食管手术以及胸主动脉瘤切除术等。这些手术需要保护非手术侧肺部,防止手术区域的污染物进入健侧肺部...
- **治疗方法**:选项 D“心脏移植术”是彻底治疗扩张型心肌病的方法之一。对于病情严重且无法通过药物或其他非手术手段治疗的患者,心脏移植可能是唯一的治疗选择。 - **其他治疗方法**:治疗心力衰竭和治疗心律...
首先,产后出血是产科最常见的严重问题之一,其发生率和死亡率均较高。产后出血可以由多种原因引起,包括胎盘滞留、凝血功能障碍、子宫收缩不良等。在处理产后出血时,首要任务是迅速止血以挽救产妇的生命,同时必须...
此外,外科手术消融,如迷宫术,能够实现更彻底的肺静脉电隔离,甚至切除左心耳,降低房颤复发。 抗栓治疗是预防血栓栓塞的关键,主要包括抗凝和抗血小板治疗。华法林是最常见的抗凝药物,可以显著降低脑卒中复发率...
7. **留置导尿**:膀胱镜检查、子宫切除术、尿道修补术及大面积烧伤等情况下需要留置导尿,但晚期胃癌患者通常不适用。 8. **降温部位**:前额、腹股沟是适合放置冰袋降温的地方,而足底不宜,因为可能导致反射性...