KANG's BLOG

Let's have some fun

分布式的核心问题:复制和分区

前言 互联网时代的用户爆发式增长,为了提供系统的可靠性、可扩展性、高性能等特点,分布式的架构方式应运而生。 想提供7x24的业务可用性,就必须让同一份数据存储在不同机器上用作备份。 为了解决并发高的问题,单一机器无法满足要求,就需要水平增加更多的机器来提升性能。 这就是分布式下的两个核心问题:复制和分区。 复制 1 为什么要复制 高可用性 当一个数据节点出现问题不能响应请求时,系统仍可以通过将请求打到其他数据节点上来保证系统的整体可用性。

分布式数据库架构类别和主流方案

一、分布式场景下数据库架构方式 1. Share nothing 顾名思义,就是什么都不共享。 Mysql 的分库分表和大部分的Nosql都是这样的方案,底层实际上完全分离,节点之间单独计算,不共享数据。 好处很明显,设计简单,扩展灵活,并行度较高。 缺点也很明显,跨分片查询困难,数据一致性难以保证。 能够实现强一致的只有zookeeper这种轻量级的分布式存储框架,但是它是牺牲了可用性的前提来保证的一致性,这也是Kafka和Dubbo这种主流中间件在逐渐抛弃zookeeper的原因,详见Zab1.0。

Kafka高性能的原因

批量处理 生产者采用批量压缩后批量发送的方式,这一批消息会被当做一个"批消息"直接由broker处理包括分发、复制、刷盘,然后发送到消费者,由消费者去分解为一条条的数据再去处理。其中broker不需要对这一批消息进行拆解处理。这样不仅减轻了broker的压力,最关重要是减少了生产和消费的交互次数。 利用PageCache加速消息读写 我们的系统读取硬盘上的数据时,并不是直接与硬盘交互,而是操作系统会将数据缓存在内存中的PageCache里,基于内存和硬盘的性能差,能最大化读写性能,当应用程序读取PageCache中数据未命中时,会触发“缺页中断”,此时应用程序的读取线程会被阻塞,操作系统把数据从文件复制到PageCache中,然后应用程序再从PageCache中继续读取数据,这时由于触发了硬盘IO,所以性能较差。 但是,操作系统对于PageCache使用后并不会直接删除,只有在内存不够用时,才会基于LRU或其他变种算法清除。 Kafka的业务属性就是不断消费刚刚写入消息,而这些新的消息不会被LRU算法优先清除,所以读取时,命中PageCache几率会非常高。 顺序读写提升磁盘IO性能 kafka充分利用磁盘顺序读写性能较好的特性来设计存储结构,它把从Producer收到的消息,顺序写入对应的log文件中,一个文件写满了,就开启一个新的文件顺序写下去。消费的时候,也是从某个log的某个位置开始,顺序读出来。 零拷贝( zero-copy ) 发送数据,通常需要通过如下几步:

分布式限流算法及方案介绍

业务场景 现代互联网很多业务场景,比如秒杀、下单、查询商品详情,最大特点就是高并发,而往往我们的系统不能承受这么大的流量,继而产生了很多的应对措施:CDN、消息队列、多级缓存、异地多活。 但是无论如何优化,终究由硬件的物理特性决定了我们系统性能的上限,如果强行接收所有请求,往往造成雪崩。 这时候限流熔断就发挥作用了,限制请求数,快速失败,保证系统满负载又不超限。 极致的优化,就是将硬件使用率提高到100%,但永远不会超过100% 常用限流算法 计数器 直接计数,简单暴力,举个例子: 比如限流设定为1小时内10次,那么每次收到请求就计数加一,并判断这一小时内计数是否大于上限10,没超过上限就返回成功,否则返回失败。 这个算法的缺点就是在时间临界点会有较大瞬间流量。

Dubbo的架构和常用配置

Dubbo架构 节点 角色说明 Provider 暴露服务的服务提供方 Consumer 调用远程服务的服务消费方 Registry 服务注册与发现的注册中心 Monitor 统计服务的调用次数和调用时间的监控中心 Container 服务运行容器 支持注册中心 nacos

Hystrix熔断器的使用

一、Hystrix使用样例: Feign中默认集成了Hystrix,可以通过@FeignClient注解标记资源并使用配置文件或API对资源进行设置,这里介绍Hystrix原生设置和使用方式 maven坐标: <dependency> <groupId>com.netflix.hystrix</groupId> <artifactId>hystrix-core</artifactId> <version>1.5.8</version> </dependency> 原生Hystrix的command定义方式: // 定义一个Command继承HystrixCommand public class HelloWorldHystrixCommand extends HystrixCommand { private final String name; public HelloWorldHystrixCommand(String name) { super(HystrixCommandGroupKey.

MQ中的消息复制方式

消息队列的主要问题 高性能 为了高可用,需要把数据写入多个节点后返回发送成功标识,才能保证某个节点挂掉后数据不丢失 写入节点数量和可靠性是成正比的,但是写入节点越多,性能越差。如果其中一个节点一直不返回,系统需要一直等待这个节点的返回,这是木桶的短板效应。 一致性 如果要确保数据一致性,必须采用主从的复制方式 RocketMQ消息复制方式 非Dledger的复制方式 分布式下一致性问题,体现在多个节点数据差异上,那么如果保证任意时刻集群都只有一个主节点,那么就可以保证数据一致性 RocketMQ的消息发送到主节点后,就认为发送成功,主从节点为固定配置,如果主节点宕机,并不会将其他从节点切换为主节点,而是等主节点恢复后,再将消息消费出去。所以一个topic下会有多个主从节点,来保证可用性。

Sentinel - 分布式系统的流量哨兵

Sentinel - 分布式系统的流量哨兵 介绍 sentinel是阿里开源的分布式流控组件,支持Dubbo、Servlet、Spring Boot / Cloud、gRPC等扩展方式,提供了流量控制、熔断降级、系统负载保护等措施来保障服务稳定。 Sentinel极为轻量,仅有200k,且无过多依赖。性能方面,25wQPS下不会对性能产生显著影响。 GitHub: https://github.

分布式锁的实现

Redis和Zookeeper实现分布式锁的区别 1.如果没获取到锁的情况下: redis分布式锁,其实需要自己不断去尝试获取锁,比较消耗性能 zk分布式锁,获取不到锁,注册个监听器即可,不需要不断主动尝试获取锁,性能开销较小 2.锁释放失败的情况下: redis获取锁的那个客户端bug了或者挂了,那么只能等待超时时间之后才能释放锁 zk的话,因为创建的是临时znode,只要客户端挂了,znode就没了,此时就自动释放锁 Zookeeper实现分布式锁 在获取分布式锁的时候在locker节点下创建临时顺序节点,释放锁的时候删除该临时节点。客户端调用createNode方法在locker下创建临时顺序节点, 然后调用getChildren(“locker”)来获取locker下面的所有子节点,注意此时不用设置任何Watcher。客户端获取到所有的子节点path之后,如果发现自己在之