分布式架构洞察与拆解

开发 架构
之前的文章更多是从微观的视角去某些每个技术的细节,而本系列的文章笔者将从宏观架构的视角来软件架构设计的那些事,希望对你有帮助。

一、详解高并发系统的关键指标

在设计一个软件系统的时候,我们需要对系统性能进行整体的评估,下面就是需要我们在日常进行系统评估和调优分析的关键指标:

(1) RT(response time):响应时间,它代表发送请求到响应数据所花费的时间,也可以理解我们web开发领域所谓的接口响应耗时,它反映了系统响应的快慢。

(2) throughput:也就是我们常说的吞吐量,它在不同的领域都有着不同的含义:

  • 业务角度:吞吐量可以代表请求数/秒、人/天或者 处理的业务数/小时
  • 网络角度:从网络角度来看,可直接用字节数/秒

针对广义上互联网领域,该指标更多反应的是系统的负载能力,在没有性能瓶颈时,服务器吞吐量计算公式为:

F= VU(虚拟用户数) * R(虚拟用户发出请求数) /T (测试时花费的时间)

  • QPS(每秒请求数):指服务器一秒内处理了多少个请求,主要用于表示读请求。
  • TPS(每秒事务数): 以高并发系统中TPS中所指的事务数包括3个过程:客户端请求服务端、服务端内部执行业务逻辑、服务端响应结果给客户端,

这里很多读者可能对于TPS和QPS的概念有写混淆,实际上TPS相较于QPS来说更能反应服务点单位时间内的一个完整的原子的事务的处理能力。 例如我们现在有个web页面,当用户打开到完全加载查看到页面内容时,这就可以理解为1个TPS,而这个页面中所有请求的接口就应该计入QPS中。

  • PV(访问量): 也就是page view,页面浏览量的意思,用户每对网站中一个完整的网页进行一次浏览就可以视为PV+1。
  • UV(独立访客):unique visitor指代某个网站或者或者链接中出现的不同的IP的数量,我们可以把ip地址视为这个访客的身份证,这意味着某个ip某天无论访问网站多少次均视为一次,这也意味着UV代表着网站某天有多少独立访客进行访问。

二、数据一体化模式

1. 详解数据一体化模式

软件发展初期,大部分软件应用都以门户、OA等系统为主,这些系统无论在访问人数还是系统数据量都是有限的。所以单体服务器就可以轻松解决这些问题。所以此时的软件架构着重追求的简单和快速迭代、成本低,所以所有程序和数据库等部署在一台服务器上,因为这种架构是将应用和数据库都存放在一台服务器上,所以我们一般称这种部署模式为数据一体化模式:

2. 监控时如何判定当前服务器是否正常

针对业务初期的数据一体化模式,性能瓶颈大概率要依赖与系统服务器指标监测,这里我们针对一个8C16G服务器并独立部署和一个单体应用和数据库的场景,给出一个比较合理的指标参考:

  • CPU利用率:一般建议高负载情况下不要超70%。
  • 负载:单核负载超过0.7就说明有问题,所以负载一般要求卡在5.6(8核*0.7)以内算正常。
  • 磁盘利用率:一般来说超过70%时就需要考虑清理一些过期的无用的垃圾数据了。
  • 堆内存占用:一般建议堆内存不要分配超过机器的一半,可以适当多一些。
  • 内存使用率:结合上述堆内存的配置,一般来说内存使用率不要超过70%超过则说明可能有内存泄漏或者程序吞吐量下降的风险。
  • GC次数和时长:这个更多是经验之谈,理论来说full gc不要在也为高峰期出现就行了,而每次垃圾回收时常stw一般不要超过200ms,这样对用户来说是无感知的,而minor gc最坏的场景一般要求每分钟不能超过1次,每次50ms以内比较合理。

关于系统负载情况的评估可以参考这篇文章:Understanding Linux CPU Load - when should you be worried?:https://scoutapm.com/blog/understanding-load-averages

三、应用与数据分离模式

1. 应用与数据分离架构简介

基于这个架构我们的业务体量有所增加,此时无论是活跃用户数量还是数据量都有所上升,这时候我们一般都会考虑增加资源,于是我们将应用和数据库分离。

这样做的好处是让软件和数据库可以专注于各自维度的优化,即应用是对外提供服务的,更着重追求CPU和内存。而数据库因为需要堆数据进行存储和索引等IO操作,更着重的是IO性能以及磁盘转速,当然对于内存要求也是有的,所以将数据库从应用服务器中分离将其部署在一台磁盘空间更大、IO性能更好的服务器上,由此提升应用整体吞吐量:

2. 关于单体应用启动前系统指标飙升问题

通过数据与应用分离,我们得到了一个更加存粹的应用系统服务器,此时调优工作会更着重于应用,假如应用启动后前几分钟,Load、RT、CPU等飙高,如何定位,可能的原因是什么?

注意问题所强调的启动后的几分钟,说明这些问题大部分是发生在启动前,一般来说服务启动可能存在如下问题:

  • 灰度发布
  • 资源初始化预热

针对问题1,这是分布式场景的问题,我们简单说明一下,假如我们日常100台服务器刚好承载业务流量,灰度发布是批次升级,这期间就可能存在不到100台服务承载100台服务器的流量,在灰度升级期间就可能存在上述指标飙高的情况。

这对问题2,就是我们的单体架构的场景了,我们的服务启动前都需要连接池、线程池、缓存预热的预热等工作,针对这种情况我们可以用例如arthas等工具进行定位排查,确保这些工作完成后再将服务暴露出去。

除了上述情况,还有可能和java语言本身的JIT机制优化,在服务初始化时,大部分代码执行过程都是通过解释后在运行的,只有在运行一段时间成为热点代码后才会生成机器码缓存,由此提升程序运行效率,针对该问题解决思路也有很多,例如:

  • 提前在业务上运行这段代码进行预热。
  • 使用JwarmUp技术保证上一次启动后的信息存储到文件中,确保下次启动时通过读取该文件提前完成JIT优化。

四、缓存与性能的提升

业务体量还在增加,特定场景下某些数据是被用户频繁查询的热点数据,在之前的架构下,获取这些信息的方式都是通过数据库查询获取,因此数据库在这个节点很可能称为系统的瓶颈。所以我们就考虑引入一个缓存中间件,针对热点数据或是通过预加载或是数据库查询后缓存的方式存放到内存中,从而提升热点数据的查询性能。

需要了解的是,一般情况下,缓存中间件可以和应用程序放在一起,但还是本着独立自治且合理利用资源的原则,我们一般建议将缓存也专门部署到一台服务器上,让其享有较大的内存空间以加载更多的数据:

有了缓存中间件之后,我们除了可以在服务启动时提前加载热点数据,对于某些不可提前预知的数据,我们可以通过如下步骤完成:

  • 查看redis是否有热点数据,如果有则直接返回,如果没有则进入步骤2。
  • 数据库查询,如果有则加载至缓存中,并将结果返回。

因为缓存数据位于内存,相较于数据库那种需要通过磁盘IO(大部分情况下,其实数据也有buffer pool)响应速度会更快一些。 但是随之而来的就是可用性和一致性等问题,例如:

  • 缓存中间挂了怎么办?
  • 缓存服务器宕机怎么办?
  • 如何解决数据库和缓存中间件数据一致性问题。

这些笔者都会在后续系列文章中补充说明。

五、分布式负载均衡

1. 分布式负载均衡架构模式

引入缓存中间件进一步提升了系统吞吐量,这时候就要考虑高并发请求性能瓶颈了,随着业务发展用户的请求量也会不断的提升,这也就是我们常说的高并发问题了,

此时我们的应用只单台服务器上,尽管各种通过各种参数调优和程序优化提升系统整体吞吐量,但毕竟应用是依赖于系统服务器的,最终都会在一个阈值上进入瓶颈而无法进一步优化,所以我们还是采用水平拓展的方式构成服务器集群,即通过更多的服务器承载单位时间内的并发请求,从而提升系统整体的吞吐量。

如下图可以看到,本次架构本质上是通过横向拓展的方式让负载均衡器通过负载均衡算法将请求分散到不同的应用服务器上,借着负载均衡器,我们还可以针对系统整体做流控、鉴权、反向代理等统一请求管理,保证系统整体安全和稳定:

2. 系统的QPS与服务器数量评估

针对分布式负载均衡,进行横向拓展时我们必须结合业务场景获得一个比较准确的估值进行服务器部署,假设每日有500w的请求,按照业界的二八原则即80%的流量都发生在20%的时间段,对此我们的推算系统QPS的步骤为:

一天24小时,而流量基本都发生在白天,所以我们实际要关注的时间段应该是12h。 对应20%的时间段即指代12*0.2即某个时间段的2h承载80%的流量,所以我们可以得到如下的计算:

(流量*80%)/(高峰时间段小时)/(每小时有多少秒)
(500_0000 * 0.8) / (12 * 0.2)/(60 * 60) ≈ 460

由此我们可以推算出系统日常情况下是QPS为460,为预防突发流量,所以峰值应该是平均高峰值的2~3倍数,所以我们认为当前场景下QPS最高应该是1500左右。 假设单台机器可承受的QPS为300,换算一下1500/300,我们大约需要5台左右的服务器,然后基于这个基准的值提前设置一下限流、熔断策略,由此高性能和高可用。

3. 服务器选型

有了上述的服务器配算方案之后,我们就需要针对性选择何时的服务器,假设我们有4C8G *16台 和 8C16G*8台,我们该选择那种方案呢?

两者服务器各有各的优势,对此我们可以从以下几个角度考虑问题:

  • 单机瓶颈:这一点很明显后者表现更加出色,假如遇到某些功能场景需要更多的核心数和内存,前者则会力不从心。
  • 容错:前者机器更多,及时单台机器出现故障,对于系统的整体影响面相较于后者会小些。
  • 负载均衡:因为前者有着更多的机器,所以对于负载均衡这种横向拓展问题发挥的空间会更大一些。
  • 连接数:MySQL分配给单机的连接数是固定的,且大公司企业都不允许调整连接数,这也就意味着有着更多的机器总的连接数也就越多。
  • GC效率:从垃圾回收器来说扫描垃圾的开销远小于回收垃圾的开销,单机有着更大的内存空间减少垃圾回收次数自然是更好的做法。

总体来说,4C8G *16台更符合现代微服务的理念,服务器更加轻量级,通过堆叠更多的服务器分散压力,对于并发处理能力、容错能力、负载均衡、连接数等方面更加友好,但还是需要考虑单机性能瓶颈和GC次数和扩容效率带来的影响。

4. 分布式架构一定比单体架构要好

单体架构也就是我们上说数据一体化模式及其进阶版本,一般发生在企业创业初期,为了快速进入市场时所诞生的系统,它要求系统越简单越好,搭建过程也是越快越好,一般来说单体架构标配为:

  • 一个应用程序
  • 一个数据
  • 一个文件服务器

它的优点如下:

  • 开发、测试、部署成本都非常低,只需针对一个项目开展,基本上可以做到前脚修改吼叫直接打包部署上线。
  • 单体程序网络基本都是数据库、redis等,不需要通过RPC与其他服务做交互,大大降低网络延迟。
  • 因为业务逻辑全部打包在单体上,不需考虑分布式锁、分布式事务、分布式id问题,只需专注解决单机并发问题即可。

由此缺点也很明显:

  • 单体架构在业务量增加后容易导致性能瓶颈。
  • 单体架构所有业务都耦合在一个程序上,随着业务演进,多人协作开发时代码耦合度非常高,测试回归成本也会急剧增加,随着时间推移可能导致开发节奏混乱、业务边界不清晰、分支合并各种冲突导致各种潜在的风险。
  • 单点故障会导致业务全瘫。
  • 这也是最为严重的一点,单体架构随着业务的拓展,按照用户展示层、业务逻辑层、数据访问层这种模式进行分层逻辑,在业务不断迭代之后,系统调用会构成下图所示的网状结构,在水平方向上来看确实比较精简,但是从垂直的角度来看,各层之间相互错中复杂的调用,导致各层都会存在依赖一个或者多个模块的情况,这对于后续的功能复用、维护、甚至是不同模块间的技术栈升级都是异常困难的。

而分布式架构对应的优点有:

  • 不同服务分布在不同的服务器上,横向拓展方便,将一个复杂的问题拆解到不同的服务上,业务边界更加清晰,降低团队的协作成本。
  • 可以灵活结合业务场景进行服务拆分、堆加服务器,快速拓展以抗住高并发流量。
  • 模块化开发,易于功能拓展和维护。
  • 单点故障问题相较于单体架构来说会相对少一些。

对应缺点:

  • 运维成本高,分布式场景我们需要针对多个服务进行部署、监控、日志、故障恢复,增加系统的复杂度,且对于分布式场景风险众多,需要考虑的问题场景相较于前者更多,对于运维、开发要求会更高。
  • 故障定位,分布式架构相较于前者更复杂,一个请求需要经过很多个服务,出现问题时的排查成本相较于单体架构来说会更高,由此还得借助分布式链路追踪。
  • 服务边界拆分维度也很困难,拆分粒度小了对于多服务运维和监控成本会增加,拆分粒度过粗又会导致服务后期变为一个臃肿的单体。
  • 分布式一致性问题,临界资源考虑的维度都是面向分布式场景,这其中就会面临分布式事务和分布式锁一致性问题。

所以对于开发周期短、业务量小、追求快速上线优先考虑使用单体架构,只有业务增长,需要考虑高并发和高可用的场景才需要考虑分布式和微服务这些。

六、读写分离

我们通过缓存中间件解决了热点数据问题,但是缓存中间件的容量毕竟是有限的,对于非热点数据我们还是需要通过数据库进行统一维护管理为了避免数据库写操作(update、insert、delete)阻塞其他事务读操作(select),因为现代主流系统架构基本都是读多写少的,所以我们更倾向于引入读写分离的方案,即让所有写操作都都面向master服务器,而读操作都通过slave服务器完成,slave通过订阅master库的bin.log进行数据实时同步操作。

在此基础上我们针对表进行优化设计,减小应用请求进行写操作时上X锁的粒度,保证写操作的吞吐量,与此同时因为读操作上的都是S锁,而S锁之间都是彼此兼容,由此通过读写分离加S锁兼容性,更进一步提升系统整体吞吐量。

七、引入CDN缓存

实际上,我们进行web网站浏览时,大部分都是基本不变的静态数据例如:JS脚本、HTML、图片文件等,考虑到访问的用户位于不同的城市,在针对这些系统资源加载的时可能会经过好几个网络路由转发才能完成资源下载,所以我们提出CDN技术即资源分发网络(Content Delivery Network),而CDN的大体工作流程是:

  • 用户通过域名针对网站发起资源请求,首先向LDNS(本地DNS)进行域名请求。
  • DNS解析域名得到对应的CNAME对应的IP地址,从而定位到对应的服务商的服务器。
  • 重点来了,服务提供商通过DNS调取系统返回给用户最佳IP地址。
  • 查看该服务器是否有请求的静态资源,如果没有则缓存并返回,若有则直接返回。

可以看到,通过CDN减轻了应用服务器的压力,大大提升的web页面的响应速度,保证了可用性和高性能:

八、分库分表

1. 详解分库分表理论思路

经过上述几轮的架构演进,软件的系统架构已经趋于稳定,随着时间的推移数据库中的数据体量也会随之逐步增加,即使通过读写分离单表数据体量已无法保证大表的快速检索,同时也考虑到并发请求的体量也在逐步增加每个数据库所能承受的最大连接数也已经无法满足现有的业务需求,所以我们又不得不考虑更进一轮的水平拓展。即分库分表方案将大表拆小,增加几台数据库服务器来分摊这些数据管理。

因为数据库分散部署,所以在进行分库分表设计时我们还需要结合一定的算法保证数据维护和检索的开销,为此我们可能还需要引入分库分表中间件来管理应用程序的数据库访问工作:

2. 如果单表数据量大,只能考虑分库分表吗

分库分表是综合解决并发和数据检索效率的综合方案,但是分库分表后会带来问题:

  • 跨库表分页
  • 分布式事务
  • 非分片键值的数据查询
  • 跨库表join关联查询

针对单表数据量大,我们可以从以下几个维度进行排查和按需设计:

  • 并发量不是很大的场景下,针对单表做好设计,建立何时的索引并采取相对简单的轻量级分区设计保证查询检索效率即可。

  • 单表数据量大,但是特定业务下这张表每日只有一些相对局限的热点数据查询请求,针对这些请求条件建立好表索引,然后借助缓存中间件来存储这些热点数据。

  • 如果需要保证高并发和高吞吐量,我们则需要借助分库分表来分散并发量和单表体量提升检索性能。

九、分布式架构

1. 详解分布式结构模式

此时我们就已经具备了一个性能性能较为出色的分布式系统架构,但是我们所有的业务都耦合在一个应用程序上,无法针对单个原子业务进行管理和优化,甚至说在高并发场景下,一些访问量和体量都比较小的业务会因为一些热点业务导致整体瘫痪,无法对外提供服务。

于是我们会尝试通过圈表并结合实际业务场景针对性的进行业务拆分,将不同的业务部署到不同的服务器上,因为这些应用之间还是存在的关联,相互之间还会存在着调用关系,所以我们还会考虑引入注册中心、配置中心、消息队列等中间件协调应用之间的通信:

2. 分布式业务架构流量突增问题

分布式系统架构下势必存在的访问量暴增的特点,假设QPS突增100倍你会怎么处理?一般来说在上文中我们已经针对系统可承受的范围内做了评估并预设了指定数量服务器来承载这些流量,对于突增的流量大部分情况下都可以拒绝掉,以保证部分用户可用以及保证系统能够维稳运行。

对此该问题,一般出现业务流量突增我们必须考虑以下两种情况:

  • 异常情况:服务被ddos攻击了。
  • 正常情况:引流或者某些原因导致业务量暴增。

针对第一种情况,我们必须采取相应防护手段处理,例如:

  • 识别攻击源。在防火墙服务器调整ACL(访问控制列表)阻断这些攻击源。
  • nginx进行限流
  • 适当增加服务器通过负载均衡分担流量。
  • 针对带宽消耗型的攻击,增加带宽适当缓解问题。
  • 路由器或防火墙启用一些反IP欺骗的功能,保证对所有IP源可见。
  • 增加对该服务的网络和web流量监控,时刻观察变化。

针对正常的业务场景则考虑从高并发系统角度进行不断拓展优化了,大抵可以从以下几个角度考虑:

  • 分布式:通过将服务拆分到不同的服务上构成分布式架构,分散管理不同业务的流量压力,进行针对性的优化,同时还能避免单功能导致服务宕机的影响面,也能提升系统的可伸缩性。
  • 集群部署:通过集群部署分散单业务服务请求的流量,结合负载均衡技术提升服务的吞吐量和响应速度,提升系统性能和可用性。
  • 缓存:对于热点数据提前缓存,提高程序读写性能和可靠性。
  • 异步处理:采用异步处理机制,例如消息队列、事件等系统,减少响应耗时、提升系统吞吐量。
  • 资源预热:将系统常见流量数据提前加载预热,减少请求的等待时间。
  • 程序优化:针对每个功能代码进行功能优化,例如:异步IO、检索锁粒度提升并发性能、减少循环递归,减少事务的粒度等。
  • 数据库优化:合理设计数据表索引、字段,以及对于一些需要join查询,我们可以结合场景进行冗余。
  • 读写分离:大部分场景都是读多写少,所以我们的数据库一般建议采用读写分离的方式,将写请求打到主库,读取请求分散到读服务器上,提升程序并发度和可扩展性,同时即时主库出现故障,从库依然可以提供服务。
  • 分库分表:为避免慢查询SQL和大量读请求,我们建议采用分库分表分散垂直和水平拆分分散请求流量和单表性能瓶颈。
  • 通过使用限流、熔断、降级等技术,防止某个组件故障导致系统崩溃的雪崩效用。
  • 监控:针对各种可能存在的风险点,通过监控建议监控观察,以保证能够及时针对做出调整和观察。

3. 关于服务限流的探讨

为什么针对流量需要进行特定的服务限流,增加服务器承载更多的流量不是更好吗?

原则上服务优先,针对这个问题要从以下两个角度考虑:

  • 服务好客户没有错,但是我们要知晓客户是否是正常客户,请求突增的原因不一定是业务量上涨,也可能是被攻击了。
  • 突发流量:出问题一般是由于突发流量,例如我们系统最高qps为1000,但是突发流量是远远高于这个数的,如果没有提前预测不做限流,服务可能直接被打卦了。

限流本质要做的就是自我保护,是系统的最后一道防线,只有通过限流保证服务器正常,然后在针对性排查流量来源,针对性扩容。

十、分布式微服务

1. 详解分布式微服务架构特点

很多读者对于分布式和微服务两个概念会有所混淆,实际上微服务相较于分布式架构做了更精细的切割,通过拆分成精细的子模块保证模块之间的高内聚低耦合,让每个模块独立存在并拆解到不同团队进行专门的维护,各个模块按照自己协定开发进行开发,公开各自的协议实现和标准,某些热点模块也可以类似于分布式架构一样进行水平拓展,保证高性能和高可用。

在部署架构上,因为微服务拆分原则是分布式架构有所不同,它拆分的目的还包含模块间的解耦和团队自治维护,所以进行模块部署的时候,多个模块以容器化的方式部署在单台服务器,也可以多个模块部署上不同服务器上,相较于分布式架构有着更加灵活的搭配和管理。

总的来说微服务架构相较于分布式架构有着更精细的拆分、有着更独立的自治性和服务异构性等特点:

2. 服务拆分后的接口机器预估

微服务架构通过更细粒度的拆分,使之业务维度有着更细粒度的解耦,所以对于特定服务的优化,我们甚至可以是针对到更细粒度的核心接口上,例如我们现在有一个查询接口,按照评估它大约是有5000QPS,经过优化后接口RT为大约是200ms,此时如果我们需要针对该模块进行水平拓展,请问需要增加几台服务器?

基于上述指标,我们首先需要针对单机性能进行大体的预估,首先接口响应实践大约是200ms,按照单台服务器单线程维护来看,每个线程在1s内可以处理5个请求:

完成线程处理能力大体评估之后,我们就需要从处理的维度进行更进一步的评估,假设这个接口CPU处理时间为2ms,而IO等待耗时为150ms,其余时间作为网络读写的耗时(读写redis数据等),这也就意味着一个线程在单位时间内只占用CPU大约10ms,也就是说单个CPU大约可以处理100个线程,也就是每个核心在理想情况下,每秒可以处理500个请求。

我们继续,默认情况下tomcat分配的线程是200,按照当前CPU处理能力每秒可以处理100个线程,所以2个核心即可在单位时间内处理掉这些线程,CPU使用率也不算很高,这个评估是合理的。 所以单机性能的核心计算还是回到了线程上,一共200个线程,每个处理5个请求,所以单机处理能力为1000QPS。

当然如果我们允许更高的CPU使用率,就可以开始使用更多的线程更高的QPS。

所以在理想情况下3000qps只需要3台服务器即可,但是我们的理论指标是基于所有理想情况,并没有考虑到应用GC情况、网络组件通信效率等综合考量做增减。

3. 微服务界面长耗时问题

通过微服务拆解,我们得到了更加灵活组合式实现高性能、高吞吐、高可用的软件架构,假设线上出现用户进入缓慢,监控服务器cpu和缓存没有什么压力,可以从哪些方面排查?

针对线上服务器多节点分布,但是在cpu和缓存没有任何压力瓶颈的情况下出现访问速度缓慢,我们大体可以从以下几个角度考虑:

  • 明确是否是用户端浏览器、网络问题。
  • 检查服务器网络带宽等,明确是否存在网络延迟丢包或者带宽限制。
  • 是否使用CDN,也有可能是CDN某个节点有问题导致用户资源加载慢。
  • 检查复杂均衡是否正确,用户请求是否打到有问题的节点上。
  • 查看期间是否存在进行耗时的GC。
  • 查看应用此时是否存在耗时的IO操作。
责任编辑:赵宁宁 来源: 写代码的SharkChili
相关推荐

2023-05-29 14:07:00

Zuul网关系统

2019-10-10 09:16:34

Zookeeper架构分布式

2013-03-22 15:55:22

Web架构架构

2023-09-14 15:38:55

云原生分布式架构

2022-06-21 08:27:22

Seata分布式事务

2011-03-11 16:02:05

2017-10-30 08:52:27

vSAN架构RAID

2022-03-06 21:43:05

Citus架构PostgreSQL

2017-09-04 08:49:17

存储原理架构

2018-12-14 10:06:22

缓存分布式系统

2019-07-19 19:53:01

2019-07-19 08:46:58

2017-09-01 05:35:58

分布式计算存储

2019-06-19 15:40:06

分布式锁RedisJava

2017-05-08 11:53:21

2018-04-03 09:27:42

分布式架构系统

2020-06-02 14:45:48

PostgreSQL架构分布式

2017-07-26 14:55:32

分布式技术架构

2017-12-20 16:15:30

分布式系统架构

2019-12-26 08:59:20

Redis主从架构
点赞
收藏

51CTO技术栈公众号