当前位置: 首页 > 科技观察

说说高并发隔离

时间:2023-03-21 23:05:31 科技观察

隔离指的是系统或资源的分离。系统隔离是在系统发生故障时限制传播和影响的范围,即发生故障后不会出现滚雪球效应,从而保证只有有问题的服务不可用,而其他服务仍然可用;资源隔离包括脏数据隔离,隔离后减少资源竞争,提高性能。我遇到比较多的隔离方式有线程隔离、进程隔离、集群隔离、机房隔离、读写隔离、动静态隔离、爬虫隔离。当系统出现问题时,可以考虑负载均衡路由、自动/手动组切换或降级来提高可用性。线程隔离线程隔离主要包括线程池隔离。在实际使用中,我们会对请求进行分类,然后交给不同的线程池进行处理。当业务请求处理出现问题时,故障不会波及到其他线程池。这确保其他服务可用。我们会根据服务级别划分两个线程池。以下是池的抽象:.level.request.async.timeout.seconds}"/>进程隔离在公司发展初期,一般先从0到1进行,不会一上来就拆分系统,这样一些比较大和将开发完整的系统。如果某个模块/功能出现问题,整个系统将不可用。第一个想到的方案是部署多个实例,然后通过负载均衡进行路由转发。系统不可用的风险。因此,该方案只是一种过渡,更好的方案是通过将系统拆分成多个子系统来实现物理隔离。通过进程隔离,一个子系统出现问题不会影响其他子系统。集群隔离随着系统的发展,单实例服务已经不能满足需求。这时候就需要面向服务的技术。通过部署多个服务,形成服务集群,提高系统容量。如下图所示,随着调用者的增多,秒杀服务刷新时会影响其他服务的稳定性。这时候就应该考虑为秒杀提供一个单独的服务集群,即服务分组,这样当某个组出现问题时,不会影响到其他组,从而实现故障隔离,如下图所示例如图中注册生产者时提供的组名:消费时使用组名即可:机房隔离随着系统可用性的要求,多-进行机房部署。每个机房的服务都有自己的服务组。机房内的服务只调用本机房的服务,不要跨机房调用;当其中一个机房服务出现问题时,可以通过DNS/负载均衡将所有请求切换到另一个机房;或者考虑服务可以自动重试其他机房的服务,提高系统可用性。一种方法是根据IP自动分组(不同机房的不同IP段),更灵活的方法是在分组名中加上机房名:读写隔离如下图所示。读写集群通过主从模式分离。读服务只从从Redis集群获取数据。当主Redis集群出现问题时,从Redis集群仍然可用。这样,用户访问不受影响;当Redis集群出现问题时,可以重试其他集群。--先读取slave状态,resp=slave_get(key)ifstatus==STATUS_OK然后返回status,valueend如果slave获取失败,从master获取状态,resp=master_get(key)动静态隔离当用户访问结算页面时,如果JS/CSS等静态资源也在结算页面系统中时,很可能会因为访问过多导致带宽满载,导致无法使用。因此,动态内容和静态资源应该分开。一般静态资源应该放在CDN上,如下图。在实际业务中,我们统计过一些页面类应用中爬虫的占比。爬虫和正常流量的比例可以达到5:1,甚至更高。在某些系统中,由于爬虫访问过多导致服务不可用;一种方案是通过限流来解决;另一种解决方案是在负载均衡层面将爬虫路由到单独的集群,以保证正常流量可用。尽可能多地流动。比如Nginx最简单的使用可以这样配置:set$flag0;if($http_user_agent~*"spider"){set$flag"1";}if($flag="0"){//Proxytonormalcluster}if($flag="1"){//Agenttocrawlercluster}我们在实际场景中使用Openresty,不仅要过滤爬虫user-agent,还要过滤一些恶意IP(IP访问统计,配置阈值),将它们分成固定的组。另一种方式是植入cookies,在访问特殊服务前植入cookies,在访问服务时验证cookies。如果没有或者错误,可以考虑验证码或者分固定组。HotspotIsolationSpike和snap-up是非常适合热点的例子;这样的热点是可以提前获知的,所以闪杀和抢购可以作为独立的系统或服务进行隔离,保证闪购/抢购过程中的问题不会影响到主进程。还有一些热点可能是由价格或突发事件引起的;对于读取热点,我使用多级缓存;而对于写热点,我们一般通过缓存+队列的方式去削峰,可以参考《前端交易型系统设计原则》。资源隔离磁盘、CPU、网络等最常见的资源;宝贵的资源将存在竞争问题。《构建需求响应式亿级商品详情页》中,我们在使用JIMDB数据同步的时候需要dump数据。SSD磁盘容量已用完50%以上。转储到同一个磁盘时,遇到容量不足的问题。我们使用单独的SAS磁盘来同步数据。另外,在使用Docker容器时,有些容器写入磁盘的频率很高,所以可以考虑为不同的容器挂载不同的磁盘。默认的CPU调度策略可能不适用于一些追求最佳性能的场景。我们希望通过将CPU绑定到特定的进程来提高性能。比如我们的一台机器会启动很多Redis实例,通过taskset将CPU绑定到Redis实例上可以提升一些性能;Nginx还提供了worker_processes和worker_cpu_affinity来绑定CPU。另外,如果系统网络应用比较繁忙,可以考虑将网卡IRQ绑定到指定的CPU上,提高系统处理中断的能力,从而提高性能。另外,大数据计算集群、数据库集群和应用集群要分开在不同的机架上,网络要尽可能隔离;因为大数据计算或者数据库同步都会有比较大的网络带宽,网络拥塞可能会导致应用响应变慢。还有其他类似的隔离技术,如环境隔离(测试环境、预发布环境/灰度环境、正式环境)、压测隔离(真实数据、压测数据隔离)、ABTest(为不同用户提供不同版本)服务)、缓存隔离(有的系统使用混合缓存,有的系统会把大字节值丢给比如Redis,导致Redis查询慢)、查询隔离(简单、批量、复杂的条件查询路由到不同的集群)等。经过隔离后,可以将风险降到最低,性能可以提高到最高。【本文为专栏作家张凯涛原创文章,作者微信公众号:凯涛的博客(kaitao-1234567)】