分布式&高并发

数据库读写分离的延迟

读写分离的数据,一般要求能够接受延时,如果不能接受,可以将写的数据放入redis,优先从redis读取。
个人猜测:不要完全读写分离,特定数据的读支持走写库

负载均衡算法

1. 轮询
2. 加权轮询
3. 随机
4. ip做hash
5. 最小连接数(负载均衡服务器能实时监测后端服务器的连接数)

SOA和微服务区别

微服务架构 = 80%的SOA服务架构思想 + 100%的组件化架构思想 + 80%的领域建模思想

为什么TCP需要4次挥手

因为TCP是全双工的协议,客户端和服务端均能收发消息,所以断开连接时,客户端需要发送请求(FIN)并接受服务端ACK;服务端也需要发送FIN请求,并接收客户端的ACK。

4层网络协议

同步和阻塞

阻塞:IO的阻塞
同步:同一时间只能执行一个任务,或者说必须等到当前请求的响应之后才能执行后续的程序。

双十一预售分流

zookeeper投票

两台机器就能PK,过半原则
Vote(myid, zxid, epoch) ,非observing状态的机器对外广播票据;
优先比较epoch,其次zxid,最后myid;
第一轮都是投自己
4种状态:Looking,leadering,following,observing
epoch每次都是从1开始自增,节点重启后又变为1,严重掉队。如果某个节点挂掉重新连接后,可能自己的epoch已经晚了很多,会借助外来的vote更新自己的epoch,然后就跟上队伍了。

zookeeper写事务分两步:本地写日志,发送follower,follower回执之后;本地commit,发送follower提交请求并接受回执。所以这种模式是强一致性

zookpper

顺序节点避免了惊(羊)群效应,解决拜占庭将军问题,基于谷歌的Chubby,雅虎搞了开源的zookeeper并捐献给Apache
客户端随机连接到集群的某个节点,如果是读请求则从当前节点读取,如果是写请求则转发的leader节点
过半提交的两阶段协议

秒杀--分段思想

个人对秒杀的思考:
如果单纯依靠分布式锁,会有如下问题:每次只有一个用户获得锁,其余用户都在等待,等待时间越长,用户体验越差,而且容易耗尽服务器连接。应该做到fast fail和fast end(自己编的词),所谓fast end,就是快速结束秒杀活动,别让用户久等。
实现:在分布式锁外边套一个队列,可以用redis实现,key="second_kill_itemid",value=秒杀数量。用户先来desr,如果返回值小于0,说明来晚了----fast fail;如果大于0,然后再进入分布式锁(如果能保证1000个线程的并发不出错也可以不用锁,毕竟已经无法超卖)。等秒杀活动结束后关闭通道并清除这个redis key。如果下订单的用户放弃付款,如果订单30分钟后过期,库存要恢复,如果商家能接受少量商品秒杀失败最好;如果商家不能接受,则30分钟后把second_kill_itemid的值恢复成0+N,前提是秒杀活动未结束(很多秒杀活动可能就2小时)。
如果条件允许,秒杀接口还可以做限流。

CAP理论

一致性(Consistency)
可用性(Availability)
分区容错性(Partition tolerance)

实时证明,大多数都是牺牲了一致性。像12306还有淘宝网,就好比是你买火车票,本来你看到的是还有一张票,其实在这个时刻已经被买走了,你填好了信息准备买的时候发现系统提示你没票了。这就是牺牲了一致性。
但是不是说牺牲一致性一定是最好的。就好比mysql中的事务机制,张三给李四转了100块钱,这时候必须保证张三的账户上少了100,李四的账户多了100。因此需要数据的一致性,而且什么时候转钱都可以,也需要可用性。但是可以转钱失败是可以允许的。

DNS可以做异地集群的就近分派

千万级流量

峰值公式:80%的请求落到20%的时间段
(1000_0000 * 0.8) / (24 * 60 * 60 * 0.2) = 463 QPS/秒
3~5台机器就足够了

缓存

浏览器缓存:缓存实时性不敏感的数据,比如:商品详情,广告,评价;但是价格、库存等就不合适。
app客户端缓存:淘宝、京东大型活动之前,经常发布新版本,把素材库提前缓存好。还有首页数据,地图数据等缓存,在性能不好的时候也有内容可以显示。
网络缓存:CDN--按流量收费,比较费钱
接入层缓存:NGINX有一定缓存能力
应用层:Redis等

缓存雪崩和击穿

三地五中心

不同地域网络供应商不一样,网络供应商自己维护DNS列表,做中间代理,上海的网络供应商把www.taobao.com => ipA,北京的把www.taobao.com => ipB

注:上边说的是前端/app访问服务端的时候;如果服务端之间的负载均衡调用,可以设计动态路由[北京地区/杭州地区]

Eureka

Eurka 工作流程:
1、Eureka Server 启动成功,等待服务端注册。在启动过程中如果配置了集群,集群之间定时通过 Replicate 同步注册表,每个 Eureka Server 都存在独立完整的服务注册表信息,集群节点之间异步复制,所以一致性并不强
2、Eureka Client 启动时根据配置的 Eureka Server 地址去注册中心注册服务
3、Eureka Client 会每 30s 向 Eureka Server 发送一次心跳请求(续约),证明客户端服务正常
4、当 Eureka Server 90s 内没有收到 Eureka Client 的心跳,注册中心则认为该节点失效,会注销该实例
5、单位时间内 Eureka Server 统计到有大量的 Eureka Client 没有上送心跳,则认为可能为网络异常,进入自我保护机制,不再剔除没有上送心跳的客户端
6、当 Eureka Client 心跳请求恢复正常之后,Eureka Server 自动退出自我保护模式
7、Eureka Client 定时全量或者增量从注册中心获取服务注册表,并且将获取到的信息缓存到本地
8、服务调用时,Eureka Client 会先从本地缓存找寻调取的服务。如果获取不到,先从注册中心刷新注册表,再同步到本地缓存
9、Eureka Client 获取到目标服务器信息,发起服务调用
10、Eureka Client 程序关闭时向 Eureka Server 发送取消请求,Eureka Server 将实例从注册表中删除

总结(AP):
讲了 Eureka 核心概念、Eureka 自我保护机制和 Eureka 集群原理。通过分析 Eureka 工作原理,通过一些列的机制,完美地解决了注册中心的稳定性和高可用性。
Eureka 为了保障注册中心的高可用性,容忍了数据的非强一致性,服务节点间的数据可能不一致, Client-Server 间的数据可能不一致。比较适合跨越多机房、对注册中心服务可用性要求较高的使用场景。
zookeeper可以认为是CP,leader选举过程服务不可用。

Eureka 是弱数据一致性,选择了 CAP 中的 AP。
Eureka 采用 Peer to Peer 模式进行数据复制。
Eureka 通过 lastDirtyTimestamp 来解决复制冲突。
Eureka 通过心跳机制实现数据修复。

一个域名可以绑定多个ip

服务降级

功能降级:商品推荐关闭
写操作降级:只更新缓存,并交由mq去修改数据库

手动降级案例:抬头库

限流

景点限流:故宫--每天门票限量
某接口每秒超过100次,多余请求拦截。
算法:

注:漏桶算法--桶里装的是请求,请求装满桶就会丢弃;令牌桶--桶里装的是立牌,令牌满了会被丢弃。
相比而言,桶算法比时间窗口算法整形更好,但不是绝对的,因为过于整形可能会误杀友好用户。

分布式限流--Redis

http://c.biancheng.net/view/5543.html
网关可以针对整体限流;也可以针对后边转发的服务集群(如用户服务集群)做限流---服务级别的限流,因为网关可以拿到要真实访问的服务名;
接口层面的限流,网关一般不做,否则维护非常困难,交由服务节点自己处理。可以采用AOP,对服务所有对外的Controller接口做统一限流,然后写注解,支持特定接口修改默认限流参数,可以通过配置中心(nacos,Appollo)动态修改。

guava的RateLimter是单节点限流
限流可以用RateLimter(每秒钟访问量),也可以用Semaphore(并发数)

保护系统的手段

paxos算法

解决分布式一致性的方案:paxos(multi-paxos)、raft、zab(zookeeper)、Gossip
raft和zab都是multi-paxos的变种。
raft:核心是连续的日志保证顺序性;zookeeper是通过队列(leader对每个follower维护一个队列)保证。
raft:每个阶段称为Term,每个节点都有一个倒计时(都是随机-减少投票轮数-加时赛),Leader节点会通过心跳来重置Follower节点的倒计时,一旦倒计时结束则会发起投票,Follower变为Candidate,Term自增,向其他节点发起投票请求,投自己。数据同步跟zab一样,都是过半的两阶段提交

Gossip:redis-cluster,consul都是这种协议。一种病毒传播模式,基于六度空间理论--两个陌生人之间不会超过6个人(平均每个人认识260个人,260的6次方超级大)。log函数可以计算,一般一个节点传播4个节点,则log以4为底20的对数

粘性

倾向于之前的选择

最小活跃数

目的:让调用慢的机器处理更少的请求

网关

zuul

Netflix公司
zuul 1.x 是BIO模型,性能低,核心是一系列过滤器:PreFilter、RoutingFilter、PostFilter、ErrorFilter
zuul 2.x 基于netty实现

gateway

属于spring cloud
netty server
一系列过滤器:GlobalFilter、RoutingFilter
可以基于Header、Cookie、Http Method、Path、Retry、Strip(剥除--做路径trim)等过滤
可以配置很多routes,当满足他的predicates时,会进入下属的一系列过滤器

spring:
  cloud:
    gateway:
      routes:
      - id: setstatus_route
        uri: http://example.org
        filters:
        - name: SetStatus
          args:
            status: 401
      - id: setstatusshortcut_route
        uri: http://example.org
        filters:
        - SetStatus=401

基于redis和令牌桶的机制实现限流:自定义过滤规则--ip、userId等
动态路由:非yml写死route规则,而是支持动态修改/增加/删除。

spring-cloud-netflix

配置中心:config
注册中心:eureca
动态配置中心:
Git webhook =>refresh Config配置中心(@RefreshScope) => Bus => 其他所有订阅服务

spring-cloud-alibaba-nacos

CP-raft协议
nacos本身是一个springboot项目,nacos=config+eureca
动态配置:也是@RefreshScope,在nacos控制台编辑
nacos源码有个RaftCore做选举
启动时和启动后每10秒(Schedule线程池实现)做一次服务注册和服务发现,另外基于UDP(DatagramSocket)会给客户端做变动推送(不用维护连接,端口信息客户端轮询时会告诉nacos),客户端在本地map有缓存服务地址列表。UDP无连接,不会对报文拆分和拼接
nacos注册的服务是临时节点,服务注册方每5秒会跟nacos做一次心跳,重置nacos的倒计时;nacos的leader和follower之间也有心跳(raft的心跳)。
nacos也有类似Euraka的自我保护机制
跟zookeeper一样有leader和follower节点,follower节点会转发事务请求到leader处理。

springcloud就是一套标准

我们可以基于它做拓展和整合,比如注册中心。

SOFAStack

蚂蚁金服的开源社区,简单理解(真实有两层逻辑)SOFA => SOA + Finacial(财务),让开发像"沙发"一样舒服。

SOFABoot

基于springboot做增强:Readiness check(springboot启动后不应该直接进流量,应该等预热之后,否则会阻塞甚至报错),类/日志隔离,spring bean异步初始化。

SOFARegistry

SOFARegistry 最早源自于淘宝毕玄的ConfigServer,采用 AP 架构,支持秒级时效性推送,同时采用分层架构支持无限水平扩展。借助 SOFABolt 通信框架,实现基于TCP长连接的节点判活与推模式的变更推送,服务上下线通知时效性在秒级以内。

SOFATracer

SOFATracer 是蚂蚁金服开发的基于 OpenTracing 规范 的分布式链路跟踪系统,其核心理念就是通过一个全局的 TraceId 将分布在各个服务节点上的同一次请求串联起来。通过统一的 TraceId 将调用链路中的各种网络调用情况以日志的方式记录下来同时也提供远程汇报到 Zipkin 进行展示的能力。
TraceId 一般由接收请求经过的第一个服务器产生,产生规则是: 服务器 IP + 产生 ID 时候的时间 + 自增序列 + 当前进程号

SOFARPC

起源于HSF,跟Dubbo、HSF一样,核心都是RPC调用,然后做熔断、降级等功能增强,只不过SOFARPC金融领域的味道重一些

SOFAMesh

SOFAMesh 是基于 Istio 改进和扩展,目前该项目将直接向 Istio 贡献

SOFABolt

Bolt 名字取自迪士尼动画-闪电狗,基于 Netty 实现的网络通信框架

SOFAJRaft

一个纯 Java 的 Raft 算法实现库, 基于百度 braft 实现而来, 使用 Java 重写了所有功能

Seata

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。

http2

请求头压缩:使用index代替各种固定的head中的key
Server Push:

但是有人测试过Http2的性能,貌似没有提升多少

Ribbon

拦截器的思想,拦截@LoadBalance注解的方法,将http://user-service/user默认通过轮询规则,解析成http://ip:port/user,ServerList是通过心跳(定时器)去Eureka更新的
@LoadBalance注解本质是@Qualifier注解

心跳:没隔多久Ping(接口Http请求)一下,如果http code是200,则ok

Ribbon和Feign区别

Ribbon配合RestTemplate可以实现负载均衡,用户可以看到http调用的逻辑。
Feign底层依赖Ribbon,

HAProxy+keepalived实现负载均衡的高可用

vip做漂移

接口状态

成功/失败,未知--> 衰减幂等重试,或者提供查询接口

Eureka和Zookeeper做注册中心的区别

https://www.cnblogs.com/zgghb/p/6515062.html
Eureka:天生为服务注册发现而设计,AP,自我保护机制,客户端缓存
Zookeeper:本身是分布式协调组件,并不是专门为注册中心设计的,CP,ZAB协议。对于服务发现来说,哪怕返回5分钟前的旧数据,也比啥都不返回好,但是zookeeper没有做到。

ES和DB数据的分布式一致性

方案1:
@Transaction
public void sync{
  数据先落DB;
  //此处异常:事务回滚,数据一致
  try{
    数据落ES;
    //此处异常:事务不回滚,但ES已有数据,mq收到消息后查询ES已有数据不再处理=>一致
    //此处宕机:事务回滚,但ES已有数据=>不一致
  }catch(Exception e){
    //此处宕机:事务回滚,但ES已有数据=>不一致
    mq.sendMsg();
    //此处异常:事务回滚,ES已有数据,mq收到消息后对ES进行覆盖同步=>不一致
    //此处宕机:事务回滚,但ES已有数据,mq收到消息后对ES进行覆盖同步=>不一致
  }

方案2:可能有几百ms延时
@Transaction
public void sync{
  Long dataId = 数据先落DB;
  //此处异常/宕机:事务回滚=>一致
  mq.sendMsg(dataId);
  //此处异常/宕机:事务回滚,mq收到消息后,查询DB没有数据不再处理=>一致
}

MQ处理方案:
监听到消息后,先去DB查询dataId信息,如果数据不存在,打印日志后不再处理;
如果数据存在,对ES进行覆盖同步,同步成功后删除消息,如果数据在DB不存在,说明中间发生了异常,可以打个warn日志

注:项目中是配置DTS订阅binlog,同步到polarDB的数据变动到ES的

秒杀

image.png

注:先过滤userId,再限流的目的是防止恶意用户挤占了普通用户。假设限流1000,恶意用户800,那普通用户的处理量就掉下来了。

3种触发降级的场景

熔断:hystrix--10秒内请求次数超过5次,错误比例超过50%,会触发5秒的熔断。
超时:平均调用时间超过阈值
资源隔离:线程池(有队列做异步缓冲-hystrix默认)或信号量(限制瞬时并发量),hystrix的信号量隔离并没有使用jdk的Semaphore,而是通过AtomicInteger做的计数器,这样没有AQS阻塞
注:hystrix和sentinel都是滑动时间窗口算法。

hystrix原理-AOP扫描@HystrixCommand

注:hystrix使用安卓中常用的rxjava(ReactiveX Java响应式编程)实现的。
hystrix源码大量使用了观察者模式配合各种事件类型:观察者,被观察者,订阅者

滑动窗口:每个窗口都统计成功、失败、超时、拒绝的次数
熔断原理:open、close、half-open
超时:
数据统计:
自动恢复:
合并请求:
缓存:

hystrix和sentinel

全链路压测

前提:不能动业务代码,应该在中间件或者组件中各种拦截器处理
数据打标:URL或Header或RpcContext
压测标记传递:ThreadLocal或派生类InheritableThreadLocal(new Thread()使用)或阿里的TransmittableThreadLocal(线程池使用)。transmittable-传动系统
外部第三方接口走Mock:发短信、支付、物流等,使用MockFilter
压测数据隔离:物理隔离和逻辑隔离。物理隔离成本高,逻辑隔离用的多,在同一个数据库实例下多创建一个影子库。redis和mq等数据,给一个较短的存活时间。
压测数据模拟:开始可以人工,后期需要构建自己的数据仓库(可以从把线上数据脱敏后拉到数据仓库)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,616评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,020评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,078评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,040评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,154评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,265评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,298评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,072评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,491评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,795评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,970评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,654评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,272评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,985评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,815评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,852评论 2 351