tradeoff(权衡),好叼的一个词!
高可用:接入层(LVS、F5承载流量的入口)、反向代理层(nginx流量url分发、限流)、网关(负责流控、风控、协议转换)、站点层(应用层)、基础服务层、存储层(DB)。网关到db中间件(zk、es、redis、mq)。
接入层(主备对外提供服务,用keepalived(主要通过发送icmp报文或者利用tcp端口连接扫描检测)检测心跳,master挂掉vip地址漂移至backup)。
nginx暴露的端口用keepalived检测,挂掉剔除。
微服务:网关、站点、基础服务。
由很多架构提供:
dubbo:
provider向registry(zk、nacos)注册服务,consumer消费。provider挂掉或者gc阻塞,注册中心通过心跳推给consumer。注册中心的功能类似keepalived。
zk:leader(事务请求的唯一调度和处理者),处理好事务后会广播给follower,半数写入成功认为成功。follower非事务处理。通过ZAB(atomic broadcast)协议选举leader,之外还有paxos、raft协议。
redis:主从和cluster分片模式。
主节点负责读写,从节点负责读。引入哨兵(sentinel)集群保证高可用,哨兵(sentinel)通过gossip(流言)协议接收关于主服务是否下线信息,使用raft协议选举出新的节点。主节点写压力过大、单点存储有上限、一主多从同步风暴。
分片模式:客户端请求通过proxy(key),根据值的区间取对应的master处理。
ES(ElasticSearch也是分片模式):基于Lucene实现。master和slave,如果主节点不可用通过bully算法选出新的主节点。主节点写,同步给副本。
MQ(KAFKA):分片、冷备。
mysql:也可分主备和分片。
继续学习redis:单线程,基于io非阻塞的多路复用,瓶颈往往在内存和网络而不在cpu。
缓存线上用redis,线下用hive。
丰富的数据类型,可用于链路追踪。当qps上去以后,可以考虑pipeline。
持久化两种文件,rdb(压缩的二进制文件,redis启动的时候还原,可以手动bgsave或者save,也可以自动)和aof(记录所有接收到的命令)。持久化过程是通过fork子进程完成的,fork的过程父进程是阻塞的。新版本可以多线程处理了,比如unlink、flushallasync等。aof是在命令执行完以后,把命令写在buffer缓冲区直接追加的,然后redis启动一个线程刷盘(每秒一次/每条命令都执行/从不存盘),一直追加文件会过大redis会自动压缩在另一个缓冲区。
如果容忍数据丢失用rdb,因为这个快。redis官网建议用rdb 或者 rdb+aof。如果redis内存满了,会剔除不活跃的数据。
java内存模型:计算机多核,由于cpu与内存(主存)速度不匹配,会配置L1L2缓存。为了cpu高效,指令可能乱序操作非原子性的(可见性、原子性、有序性)。为了高效出现多线程,会出现1、缓存数据不一致(多线程修改共享变量,cpu核心下的高速缓存是不共享的):总线锁(当前cpu修改,其他cpu只能等)和缓存一致协议(mesi:modified修改状态、exclusive独占状态、share共享状态、invalid无效状态)(如果独占和共享的状态,数据是最新的。修改状态,其他cpu会置为无效同时改位独占状态)。
为了提高效率引入内存缓冲区(store buffer/invalid queue)来实现异步。有些情况需要可见性和有序性,加入读屏障/写屏障/全能屏障来保证cpu可见和有序。
多线程: