0%

什么是单元化?

单元化,是业务在容灾能力建设,水平伸缩能力建设中的一种架构实现,单元是业务以某种维度划分的分片,业务流量可以按照比例在单元间调度,与一般的多地域跨机房多活不一样的是,跨机房多活一般在数据库层面不进行拆分,不能多活。而单元化中业务逻辑处理是闭环的(分片自治,分而治之),每个单元拥有处理业务逻辑的所有资源(服务能力与数据)

单元化技术特点

  1. 单元以某种维度进行划分(地域,商户id,用户id等),业务逻辑处理封闭在单元内部,单元间的流量可以按照路由规则灵活调拨
  2. 单元间的数据同步,相互备份,每个单元在同城(异地)可以在故障期间相互接管

单元化的切分思路

  1. 按业务类型
  2. 用户id
  3. 按地理位置 (外卖/打车/地图服务:商家用户、骑手都在同一地域)

单元化的业务场景

流水单据型(改造相对容易)

  • 业务应用场景:典型的业务场景如电商交易,账单流水
  • 数据特点:多笔业务数据不互相关联,按照一定维度进行分片可接受最终一致

状态型数据(双活不好做)

  • 业务应用举例:比如账户余额数据
  • 数据特点:状态数据是全局状态的,每笔业务能否成功执行依赖数据状态的准确性。对于状态性数据要保证强一致性,账户余额需要优先保证一致性,不然容易资损

构建/多活时面临的数据的技术解决方案

所谓的多活可以理解成多主结构,也就是多地可写

在单活的场景下,通常依靠mysql主从进行数据,多活场景下,可以类似主从的方案,借助mysql repluation 协议信息进行数据的同步

实现原理:

主要问题

数据回环

如果对同步的数据不加过滤仍由其在不同SET的数据库中来回复制,不仅消耗大量的网络带宽,最终还会导致数据不一致。
常见的解决办法
    1. 引入额外字段,在表中添加额外字段标注机房信息,但缺点是要侵入业务表
    2. GTID,mysql的原生实现,在事务中标注信息,但只能用于mysql的双向同步
    3. 对SQL打标,在sql hint中标注sql产生的机房,在回环同步时写入时如果发现是同机房产生的则过滤掉,此方案不仅能跨数据源,对业务侵入也小,但需要有额外的同步开销

数据一致性校验

存量数据如何同步,增量数据同步过程中,如何解决冲突问题。
冲突的解决策略办法

跨地域同步性能问题

双写冲突(容灾切换期间)

单元化改造路径

单元化的方案一般不是一开始就基于单元化去实现的,大多都是基于业务的发展,

什么是时钟频率?脉冲信号的振荡是由什么产生的?什么是实时时钟?

作者:知乎用户
链接:https://www.zhihu.com/question/20904763/answer/87166311
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

时钟都是通过振荡器产生的。振荡器有很多种,根据不同的时钟需求会使用不同的振荡器。原始时钟信号一般会通过晶体振荡器产生。晶体振荡器的特点是根据晶体特性存在一个谐振频率,而且品质因子Q(目标频率能量占总能量的比值)非常高。这能够产生一个噪声非常小、震荡频率非常精确的时钟信号。对于精度要求不那么高的时钟,也有使用LC振荡器或者环形振荡器生成的。次级时钟信号可以通过将主时钟信号输入分频/倍频电路得到,比如锁相环。锁相环的核心是鉴相器和压控振荡器。鉴相器比较输入时钟信号和输出时钟信号的相位差别,并将相位信号转化为电压信号,然后这个电压信号通过压控振荡器变为输出时钟信号。由于反馈回路的存在,输入和输出时钟会保持一个固定的相位差,这意味着两者频率完全相同。通过在鉴相器输入端加入分频器,可以实现非整数倍倍频和分频电路。还有一类通过外部输入信号产生时钟的电路——CDR(clock data recovery)。因为外部输入的信号使用的是外部的时钟,和本地时钟存在同步问题,所以无法直接使用本地时钟采样。如果没有外部时钟输入,就必须从输入的信号中还原出外部时钟,这就是CDR电路。CDR的基础结构和锁相环挺相似的,但是在滤波和鉴相电路上做了修改以保证输出时钟的稳定性,具体就不展开了。

上面这些没有电路基础大概看不懂吧……需要时钟的理由稍微简单一点……任何电路都是有延迟的,从输入信号输入到电路完成计算输出结果是需要时间的。但是麻烦的是这个时间对于所有电路都是不一样的,所以我们不知道究竟要等多久上一个电路才算是完成了运算,可以读取输出了。对于人来说这个问题还不大,我们只要多等等保证算完了就好了,但是对于电路来说就麻烦了:每一级电路都需要上一级电路的输出结果作为输入,可是要等多久上一级才能完成计算?就算我知道上一级的计算需要10ns时间,但是我该从哪里开始计时?用什么进行计时?于是电路设计师们不得不加入了非常复杂的“握手信号”来控制数据读取,简单的说就是前一级电路在完成运算之后向下一级发送一个“可以读取了”的信号,下一级收到这个信号之后才能读取;下一级读取完毕之后再发一个“我读完了”的信号返回上一级,上一级才能开始下一个运算。这不仅浪费了大量的电路在握手上,还极大地加大了设计难度。

为了解决这个问题,工程师们设计了“同步电路”。同步电路加入了时钟信号,所有电路模块的读取与输出都受到时钟信号的控制。比如一个电路模块,每次计算需要至多100ns的时间,而电路的时钟周期是50ns。那么我就知道这个电路至多需要两个周期的时间就能完成运算。为了冗余安全,我将这个模块设计为每三个时钟周期进行一次运算,它的下一级电路也每隔三个周期执行一次读取即可。有了时钟信号,我只需要对每个电路设计“隔几个周期进行读/写”即可,不再需要在所有模块之间都设计握手信号,这极大地降低了设计难度。指令执行周期指的是一条CPU指令,需要多少个CPU时钟周期(一个时钟周期内时钟信号震荡一次)完成。典型RISC架构一条指令至少需要4个周期:一个周期读取指令一个周期读取执行指令所需的数据一个周期执行指令一个周期写入执行结果可以看到这四个步骤是不同的电路模块负责的,在其中一个模块工作时,其他模块是空闲的。为了不浪费其他模块的时间,处理器采用了流水线结构,4条指令并行处理:首先读取第一条指令。第一条指令读取数据的时候,第二条开始读取指令。第一条指令执行的时候,第二条开始读取数据,第三条开始读取指令。第一条写入结果的时候,第二条开始执行,第三条开始读取数据,第四条开始读取指令。第二条写入结果的时候,第三条开始执行,第四条开始读取数据,第五条开始读取指令。……实际上的处理器架构和指令都会更加复杂,所以需要更多的时钟周期才能处理。

背景

交接过来的的服务,在上游服务调用服务的过程会偶发调用超时,通过观察监控,可以看到超时的时候和服务端gc的时间点一致,基本定位是gc导致的问题

通用的解决办法

Read more »