精华内容
下载资源
问答
  • 云存储技术

    2020-06-09 11:10:27
    4、网络存储的综合运用则基于复合型业务应用场景,讲述如何融合运用DAS、SAN和NAS技术实现WEB应用服务器的负载均衡、基于集群的高可用WEB服务器部署、远程异地灾备中心、远程异地数据同步等业务的应用。该部分内容...
  • 登录后将显示如图所示的内容。让我们快速浏览一下仪表板中包含的内容。 image.png Schema Record Types Users无法法删除CloudKit生成的记录类型。但是,您可以将其他字段添加到此记录类型。顾名思义,“用户”...

    登录CloudKit Dashboard

    地址:https://icloud.developer.apple.com/dashboard
    登录后将显示如图所示的内容。让我们快速浏览一下仪表板中包含的内容。

    image.png

    Schema Record Types

    Users无法法删除CloudKit生成的记录类型。但是,您可以将其他字段添加到此记录类型。顾名思义,“用户”记录类型用于存储有关使用您的应用程序的每个用户的信息。
    从“记录类型”列中选择记录类型时,详细信息窗格将更新以显示与所选类型相关的所有字段。您还可以在此处为给定记录类型设置元数据索引和安全设置。
    您可以通过单击详细信息窗格左上角的+符号来创建新类型,如下图

    image.png

    然后要求您命名新类型。在保存之前输入名称很重要,因为一旦保存类型就无法更改名称。注意,将为每种记录类型自动创建“创建”和“修改”字段。您不能删除这些字段。还有一个自动添加的字段,您应在保存之前进行更改。要添加其他字段,只需单击“添加字段...”链接。您可以在首次创建类型时添加所有字段,以后再更新它们,或者在开发模式下允许您的应用通过代码动态添加新字段时,可以添加所有字段。从图下可以看到,字段类型有多个选项,可以是单个条目也可以是列表。

    Jietu20200527-144957@2x.jpg

    最后,您可以为各个字段设置索引,这很重要,如果您发现您的应用始终在查询记录类型的特定字段。
    如果在保存后意识到不再需要新的记录类型,则只需从列表中选择类型,然后单击详细信息窗格中的垃圾桶图标将其删除。对于“用户”类型,垃圾桶被禁用,因为您无法删除该类型。
    如果添加了不再需要的字段,请选择记录类型,然后将光标悬停在要删除的字段上。

    Security Roles

    架构下的“安全角色”部分使您可以控制谁可以更新,创建和查看不同的记录类型。这是一个两步过程。首先,您必须创建一个安全角色。其次,您必须将该角色添加到希望授予这些权限的用户。
    默认情况下,不创建任何安全角色。要创建一个新的,请单击详细信息窗格中的+号。要求您命名角色。这样做,然后单击“保存”。现在,您可以为记录类型分配权限。您可以根据需要为每个安全角色添加任意数量的记录类型权限,并且可以授予每个安全角色创建,读取或写入给定记录类型的权限。

    推荐

    基础文章推荐

    经典教程推荐

    技术源码推荐

    推荐文章

    CoreData篇

    Combine篇

    TextField篇

    JSON文件篇


    一篇文章系列

    技术交流

    QQ:3365059189
    SwiftUI技术交流QQ群:518696470

    展开全文
  • shadowcloud是增强的云存储客户端。 Статьянарусском: ://habr.com/post/428523/ 产品特点 允许将不同存储用作一个“驱动器”(虚拟区域) 启用随机文件访问,媒体流 删除文件大小,文件名等...
  • 这是一个WordPress插件,可让您通过云存储服务来提供WordPress媒体库文件。 产品特点 通过MIME类型限制卸载 从原始服务器删除文件选项 创建超链接并输出图像标签 :NEW_button: CloudFlare支持( ) 贡献 您可以...
  • :high_voltage: 无服务器ffmpeg 桶事件驱动的FFMPEG具有功能 部署和使用演示 入门 请参阅部署以获取有关如何部署到AWS的注释。...这也将删除您所有存储桶中的内容! :warning: npm run stack-destroy 建于
  • 同步切图结果至云存储(在最后一个协程执行成功之后操作数据库) 3.redis是连接外网 使用db为9 4:端口9502 开始正题: 今天将一个字段内容的格式修改了 字段名称叫: view_url,原来保存格式是: ...
  • 云存储   1,小程序端 1-1,首页 首页有以下几个功能点 点餐 菜单浏览 排号等位 拨打电话 顶部轮播图 搜索菜品 这里点餐分两种 1,可以设置直接点餐 直接点餐:适合小型饭店,或者奶茶类快餐店。直接就...
  • 文章来源:腾讯容器团队 /原文链接作者蔡靖,...本次分享以 controller manager 未能正常挂载 volume 致使 pod 启动失败案例展开,通过问题根因分析过程以及如何制定解决方案等内容,帮助大家深入理解 k8s at...

    59057298b44c655c0b8ef2556914b915.png

    文章来源:腾讯云容器团队 / 原文链接

    作者蔡靖,腾讯高级后台开发工程师,拥有多年大规模 Kubernetes 集群开发运维经验。目前负责腾讯云 TKE 存储组件的功能特性实现,以及稳定性与性能的提升。本次分享以 controller manager 未能正常挂载 volume 致使 pod 启动失败的案例展开,通过问题根因分析过程以及如何制定解决方案等内容,帮助大家深入理解 k8s attach/detach controller。

    1. 前言

    本文主要通过深入学习 k8s attach/detach controller 源码,挖掘出 controller manager 未能正常挂载 volume 致使 pod 启动失败这一案例发生 attach/detach controller bug 的根因,进而给出解决方案。

    看完本文你将学习到:

    • attach/detach controller 的主要数据结构有哪些,保存什么数据,数据从哪来,到哪去等等;

    • k8s attach/detach volume 的详细流程,如何判断 volume 是否需要 attach/detach,attach/detach controller 和 kubelet (volume manager) 如何协同工作等等。

    2. 案例背景

    本节我们首先了解下案例的问题和现象;然后去深入理解 ad controller 维护的数据结构;之后根据数据结构与 ad controller 的代码逻辑,再来详细分析案例出现的原因和解决方案,从而深入理解整个 ad controller。

    2.1 问题描述

    • 一个 statefulsets(sts) 引用了多个 pvc cbs,我们更新 sts 时,删除旧 pod,创建新 pod,此时如果删除旧 pod 时 cbs detach 失败,且创建的新 pod 调度到和旧 pod 相同的节点,就可能会让这些 pod 一直处于ContainerCreating 。

    2.2 现象

    • kubectl describe pod

    7de3d540572f9e36df078eade68e715b.png

    • kubelet log

    46b19abba91068a8f26561b354ab71ba.png
    • kubectl get node xxx -oyaml 的volumesAttachedvolumesInUse

    volumesAttached:
    - devicePath: /dev/disk/by-id/virtio-disk-6w87j3wv
    name: kubernetes.io/qcloud-cbs/disk-6w87j3wv
    volumesInUse:
    - kubernetes.io/qcloud-cbs/disk-6w87j3wv
    - kubernetes.io/qcloud-cbs/disk-7bfqsft5

    3. k8s 存储简述

    k8s 中 attach/detach controller 负责存储插件的 attach/detach。本文结合一个具体案例来分析 ad controller 的源码逻辑,该案例是因 k8s 的 ad controller bug 导致的 pod 创建失败。

    k8s 中涉及存储的组件主要有:attach/detach controller、pv controller、volume manager、volume plugins、scheduler。每个组件分工明确:

    • attach/detach controller:负责对 volume 进行 attach/detach。

    • pv controller:负责处理 pv/pvc 对象,包括 pv 的 provision/delete(cbs intree的provisioner设计成了external provisioner,独立的 cbs-provisioner 来负责 cbs pv 的 provision/delete)。

    • volume manager:主要负责对 volume 进行 mount/unmount。

    • volume plugins:包含 k8s 原生的和各厂商的的存储插件。

      • 原生的包括:emptydir、hostpath、flexvolume、csi 等。

      • 各厂商的包括:aws-ebs、azure、我们的 cbs 等。

    • scheduler:涉及到 volume 的调度。比如对 ebs、csi 等的单 node 最大可 attach 磁盘数量的 predicate 策略。

    f984584ed2c681e54815a12cbc293833.png

    控制器模式是 k8s 非常重要的概念,一般一个 controller 会去管理一个或多个 API 对象,以让对象从实际状态/当前状态趋近于期望状态。

    所以 attach/detach controller 的作用其实就是去 attach 期望被 attach 的 volume,detach 期望被 detach 的 volume。

    后续 attach/detach controller 简称 ad controller。

    4 ad controller 深度分析

    4.1 ad controller数据结构

    对于 ad controller 来说,理解了其内部的数据结构,再去理解逻辑就事半功倍。ad controller 在内存中维护 2 个数据结构:

    1. actualStateOfWorld —— 表征实际状态(后面简称 asw)

    2. desiredStateOfWorld —— 表征期望状态(后面简称 dsw)

    很明显,对于声明式 API 来说,是需要随时比对实际状态和期望状态的,所以 ad controller 中就用了 2 个数据结构来分别表征实际状态和期望状态。

    actualStateOfWorld

    actualStateOfWorld 包含2个 map:

    • attachedVolumes:包含了那些 ad controller 认为被成功 attach 到 nodes 上的 volumes。

    • nodesToUpdateStatusFor:包含要更新node.Status.VolumesAttached 的 nodes。

    attachedVolumes
    如何填充数据?

    1、在启动 ad controller 时,会 populate asw,此时会 list 集群内所有 node 对象,然后用这些 node 对象的node.Status.VolumesAttached 去填充attachedVolumes

    2、之后只要有需要 attach 的 volume 被成功 attach 了,就会调用MarkVolumeAsAttached(GenerateAttachVolumeFunc 中)来填充到attachedVolumes中

    如何删除数据?

    只有在 volume 被 detach 成功后,才会把相关的 volume 从attachedVolumes中删掉。(GenerateDetachVolumeFunc 中调用MarkVolumeDetached)。

    nodesToUpdateStatusFor
    如何填充数据?

    detach volume 失败后,将 volume add back 到nodesToUpdateStatusFor

    GenerateDetachVolumeFunc 中调用AddVolumeToReportAsAttached

    如何删除数据?

    在 detach volume 之前会先调用RemoveVolumeFromReportAsAttached 从nodesToUpdateStatusFor中先删除该 volume 相关信息。

    desiredStateOfWorld

    desiredStateOfWorld 中维护了一个 map:

    nodesManaged:包含被 ad controller 管理的 nodes,以及期望 attach 到这些 node 上的 volumes。

    nodesManaged
    如何填充数据?

    1、在启动 ad controller 时,会 populate asw,list 集群内所有 node 对象,然后把由 ad controller 管理的 node 填充到nodesManaged

    2、ad controller 的nodeInformer watch 到 node 有更新也会把 node 填充到nodesManaged

    3、另外在 populate dsw 和podInformer watch 到 pod 有变化(add, update)时,往nodesManaged 中填充 volume 和 pod 的信息。

    4、desiredStateOfWorldPopulator 中也会周期性地去找出需要被 add 的 pod,此时也会把相应的 volume 和 pod 填充到nodesManaged

    如何删除数据?

    1、当删除 node 时,ad controller 中的nodeInformer watch 到变化会从 dsw 的nodesManaged 中删除相应的node。

    2、当 ad controller 中的podInformer watch 到 pod 的删除时,会从nodesManaged 中删除相应的 volume 和 pod。

    3、desiredStateOfWorldPopulator 中也会周期性地去找出需要被删除的 pod,此时也会从nodesManaged 中删除相应的 volume 和 pod。

    4.2 ad controller 流程简述

    ad controller 的逻辑比较简单:

    1、首先,list 集群内所有的 node 和 pod,来populate actualStateOfWorld (attachedVolumes )和desiredStateOfWorld (nodesManaged)。

    2、然后,单独开个 goroutine 运行reconciler,通过触发 attach, detach 操作周期性地去 reconcile asw(实际状态)和 dws(期望状态)。

    • 触发 attach,detach 操作也就是,detach 该被 detach 的 volume,attach 该被 attach 的 volume。

    3、之后,又单独开个 goroutine 运行DesiredStateOfWorldPopulator ,定期去验证 dsw 中的 pods 是否依然存在,如果不存在就从 dsw 中删除。

    5 案例分析

    接下来结合上面所说的案例,来详细看看reconciler的逻辑。

    5.1 案例初步分析

    • 从 pod 的事件可以看出来:ad controller认为 cbs attach 成功了,然后 kubelet 没有 mount 成功。

    • 但是从 kubelet 日志却发现Volume not attached according to node status ,也就是说 kubelet 认为 cbs 没有按照 node 的状态去挂载。这个从 node info 也可以得到证实:volumesAttached 中的确没有这个 cbs 盘(disk-7bfqsft5)。

    • node info 中还有个现象:volumesInUse 中还有这个 cbs。说明没有 unmount 成功

    很明显,cbs 要能被 pod 成功使用,需要 ad controller 和 volume manager 的协同工作。所以这个问题的定位首先要明确:

    1. volume manager 为什么认为 volume 没有按照 node 状态挂载,ad controller 却认为 volume attch 成功了?

    2. volumesAttachedvolumesInUse 在 ad controller 和 kubelet 之间充当什么角色?

    这里只对分析 volume manager 做简要分析。

    • 根据Volume not attached according to node status 在代码中找到对应的位置,发现在GenerateVerifyControllerAttachedVolumeFunc 中。仔细看代码逻辑会发现,volume manager 的 reconciler 会先确认该被 unmount 的 volume 被 unmount 掉,然后确认该被 mount 的 volume 被 mount。
      • 此时会先从 volume manager 的 dsw 缓存中获取要被 mount 的 volumes(volumesToMountpodsToMount );
      • 然后遍历,验证每个volumeToMount是否已经 attach 了。这个volumeToMount是由podManager中的podInformer加入到相应内存中,然后desiredStateOfWorldPopulator周期性同步到 dsw 中的;
      • 验证逻辑中,在GenerateVerifyControllerAttachedVolumeFunc中会去遍历本节点的node.Status.VolumesAttached,如果没有找到就报错(Volume not attached according to node status);
    • 所以可以看出来,volume manager 就是根据 volume 是否存在于node.Status.VolumesAttached 中来判断volume 有无被 attach 成功
    • 那谁去填充node.Status.VolumesAttached ?ad controller 的数据结构nodesToUpdateStatusFor 就是用来存储要更新到node.Status.VolumesAttached 上的数据的。
    • 所以,如果 ad controller 那边没有更新node.Status.VolumesAttached,而又新建了 pod,desiredStateOfWorldPopulator 从podManager中的内存把新建 pod 引用的 volume 同步到了volumesToMount中,在验证 volume 是否 attach 时,就会报错(Volume not attached according to node status)。
      • 当然,之后由于 kublet 的 syncLoop 里面会调用WaitForAttachAndMount 去等待 volumeattach 和 mount 成功,由于前面一直无法成功,等待超时,才会有会面timeout expired 的报错。

    所以接下来主要需要看为什么 ad controller 那边没有更新node.Status.VolumesAttached

    5.2 ad controller 的reconciler详解

    接下来详细分析下 ad controller 的逻辑,看看为什么会没有更新node.Status.VolumesAttached,但从事件看 ad controller 却又认为 volume 已经挂载成功。

    从流程简述中表述可见,ad controller 主要逻辑是在reconciler中。

    一、reconciler定时去运行reconciliationLoopFunc,周期为 100ms。

    二、reconciliationLoopFunc的主要逻辑在reconcile()中:

    1. 首先,确保该被 detach 的 volume 被 detach 掉

    • 遍历 asw 中的attachedVolumes,对于每个 volume,判断其是否存在于 dsw 中:根据 nodeName 去 dsw.nodesManaged 中判断 node 是否存在;存在的话,再根据 volumeName 判断 volume是否存在。

    • 如果 volume 存在于 asw,且不存在于 dsw,则意味着需要进行 detach;

    • 之后,根据node.Status.VolumesInUse来判断 volume 是否已经 unmount 完成,unmount 完成或者等待 6min timeout 时间到后,会继续 detach 逻辑;

    • 在执行 detach volume 之前,会先调用RemoveVolumeFromReportAsAttached从 asw 的nodesToUpdateStatusFor中去删除要 detach 的 volume;

    • 然后 patch node,也就等于从node.status.VolumesAttached删除这个 volume;

    • 之后进行 detach,detach 失败主要分 2 种:

    1. 如果真正执行了volumePlugin的具体实现DetachVolume失败,会把 volume add back 到nodesToUpdateStatusFor(之后在 attach 逻辑结束后,会再次 patch node);

    2. 如果是 operator_excutor 判断还没到 backoff 周期,就会返回backoffError,直接跳过DetachVolume;

    • backoff 周期起始为 500ms,之后指数递增至 2min2s。已经 detach 失败了的 volume,在每个周期期间进入 detach 逻辑都会直接返回backoffError

    2.  之后,确保该被 attach 的 volume 被 attach 成功

    • 遍历dsw的nodesManaged,判断 volume 是否已经被 attach 到该 node,如果已经被 attach 到该 node,则跳过 attach 操作;

    • 去 asw.attachedVolumes 中判断是否存在,若不存在就认为没有 attach 到 node;若存在,再判断 node,node 也匹配就返回attachedConfirmed

    • attachedConfirmed是由 asw 中AddVolumeNode去设置的,MarkVolumeAsAttached设置为 true(true 即代表该 volume 已经被 attach 到该 node 了);之后判断是否禁止多挂载,再由 operator_excutor 去执行 attach。

    3. 最后,UpdateNodeStatuses去更新 node status。

    5.3 案例详细分析

    • 前提

      • volume detach 失败

      • sts+cbs(pvc),pod recreate 前后调度到相同的 node

    • 涉及 k8s 组件

      • ad controller

      • kubelet(volume namager)

    • ad controller 和 kubelet (volume namager) 通过字段node.status.VolumesAttached交互。

      • ad controller 为node.status.VolumesAttached新增或删除 volume,新增表明已挂载,删除表明已删除

      • kubelet(volume manager)需要验证新建pod中的(pvc 的) volume 是否挂载成功,存在于node.status.VolumesAttached中,则表明验证 volume 已挂载成功;不存在,则表明还未挂载成功。

    • 以下是整个过程:

    • 首先,删除 pod 时,由于某种原因 cbs detach 失败,失败后就会 backoff 重试。

    1. 由于 detach 失败,该 volume 也不会从 asw 的attachedVolumes中删除

    由于 detach 时,

    1. 先从node.status.VolumesAttached中删除 volume,之后才去执行 detach

    2. detach时返回backoffError不会把该 volumeadd back node.status.VolumesAttached

    之后,我们在 backoff 周期中(假如就为第一个周期的 500ms 中间)再次创建 sts,pod 被调度到之前的 node

    而 pod 一旦被创建,就会被添加到 dsw 的nodesManaged(nodeName 和 volumeName 都没变)

    reconcile()中的第 2 步,会去判断 volume 是否被 attach,此时发现该 volume 同时存在于 asw 和 dws 中,并且由于 detach 失败,也会在检测时发现还是 attach,从而设置attachedConfirmed为 true

    ad controller 就认为该 volume 被 attach 成功了

    reconcile() 中第 1 步的 detach 逻辑进行判断时,发现要 detach 的 volume 已经存在于dsw.nodesManaged了(由于 nodeName 和 volumeName 都没变),这样 volume 同时存在于 asw 和 dsw 中了,实际状态和期望状态一致,被认为就不需要进行 detach 了。

    这样,该 volume 之后就再也不会被 add back 到node.status.VolumesAttached。所以就出现了现象中的 node info 中没有该 volume,而 ad controller 又认为该 volume 被 attach 成功了

    由于kubelet(volume manager)与 controller manager 是异步的,而它们之间交互是依据node.status.VolumesAttached ,所以volume manager在验证volume是否attach成功,发现node.status.VolumesAttached中没有这个 voume,也就认为没有 attach 成功,所以就有了现象中的报错Volume not attached according to node status

    之后 kubelet 的syncPod在等待 pod 所有的 volume attach 和 mount 成功时,就超时了(现象中的另一个报错timeout expired wating...)。

    所以 pod 一直处于ContainerCreating

    5.4 小结

    • 所以,该案例出现的原因是:

      • sts+cbs,pod recreate 时间被调度到相同的 node;

      • 由于 detach 失败,backoff 期间创建 sts/pod,致使 ad controller 中的 dsw 和 asw 数据一致(此时该 volume 由于没有被 detach 成功而确实处于 attach 状态),从而导致 ad controller 认为不再需要去 detach 该 volume;

      • 又由于 detach 时,是先从node.status.VolumesAttached中删除该 volume,再去执行真正的DetachVolume。backoff 期间直接返回backoffError,跳过DetachVolume,不会 add back;

      • 之后,ad controller 因 volume 已经处于 attach 状态,认为不再需要被 attach,就不会再向node.status.VolumesAttached中添加该 volume;

      • 最后,kubelet 与 ad controller 交互就通过node.status.VolumesAttached,所以 kubelet 认为没有 attach 成功,新创建的 pod 就一直处于ContianerCreating了。

    • 据此,我们可以发现关键点在于node.status.VolumesAttached和以下两个逻辑:

    1. detach 时 backoffError,不会 add back;

    2. detach 是先删除,失败再 add back。

    所以只要想办法能在任何情况下 add back 就不会有问题了。根据以上两个逻辑就对应有以下 2 种解决方案,推荐使用方案2
    1. backoffError 时,也 add back
    • 但这种方式有个缺点:patch node的请求数增加了10+次/(s * volume)

    • pr #72914——https://github.com/kubernetes/kubernetes/pull/72914

    一进入 detach 逻辑就判断是否 backoffError(处于 backoff 周期中),是就跳过之后所有 detach 逻辑,不删除就不需要 add back 了。

    • 这个方案能避免方案 1 的问题,且会进一步减少请求 apiserver 的次数,且改动也不多

    • pr #88572——https://github.com/kubernetes/kubernetes/pull/88572

    总结

    AD Controller 负责存储的 Attach、Detach。通过比较 asw 和 dsw 来判断是否需要 attach/detach。最终 attach 和 detach 结果会体现在node.status.VolumesAttached。以上案例出现的现象,是 k8s ad controller 的 bug 导致,目前社区并未修复。

    • 现象出现的原因主要是:

      • 先删除旧 pod 过程中 detach 失败,而在 detach 失败的 backoff 周期中创建新 pod,此时由于 ad controller 逻辑 bug,导致 volume 被从node.status.VolumesAttached中删除,从而导致创建新 pod 时,kubelet 检查时认为该 volume 没有 attach 成功,致使 pod 就一直处于ContianerCreating

    • 而现象的解决方案,推荐使用 pr #88572——https://github.com/kubernetes/kubernetes/pull/88572

    • 目前 TKE 已经有该方案的稳定运行版本,在灰度中。

    END
    Kubernetes  CKA线下班40a7f50a8d4baa873ca311433a4c44de.png

    d6ec9fdc23e50a222f95a74d196d9579.gif

    1db6a0ce6fa504f1191fe9aa59b5595d.png

    展开全文
  • 基于rsync文件增量同步方案

    千次阅读 2017-04-27 18:21:00
    文件同步是云盘功能重要部分(包括文件内容的同步和文件增删同步,应该有上传、下载、创建、删除等动作,但在本文叙述中,主要关注文件内容的传输,即上传、下载),如何快速高效地进行文件同步,就成了云盘...
        

    背景

    犀牛云盘是美团点评内部一个基于美团云的文件协作平台,核心是文件的结构化云存储以及上传和下载的体验优化。文件同步是云盘功能的重要部分(包括文件内容的同步和文件增删的同步,应该有上传、下载、创建、删除等动作,但在本文的叙述中,主要关注文件内容的传输,即上传、下载),如何快速高效地进行文件同步,就成了云盘亟需解决的技术难题。本文阐述的方案就是在这种场景下提出来的,我们希望通过rsync增量传输算法,来提高文件同步速度。但原始rsync算法在高并发的服务上会存在性能问题,所以本方案也借鉴zsync的思路,做了优化。

    rsync增量传输算法

    rsync增量传输算法首度发表于1996年6月19日,原始作者为Andrew Tridgell与Paul Mackerras [1]。实现增量传输的主要过程,就是差异检测和差异数据组织及传输,前者是rsync增量传输算法的核心。

    rsync增量传输算法是一种滑动块差异检测算法。以检测文件A和B的差异为例,首先对A按固定长度L划分为若干块,并对每一块生成弱摘要(Adler-32:速度快)和强摘要(MD5:鉴别度高),然后对B从第一个字节开始,以长度为L的滑动窗口,遍历整个文件,计算每个窗口块的弱、强摘要,并与A中的摘要值进行比较,弱、强摘要都相同者,即视为相同数据块,否即为差异块。如下图所示:

    rsync差异检测示意图

    rsync增量传输算法主要有两个特点:

    • 固定块摘要和滑动块检测的结合,提高命中率;
    • 弱摘要和强摘要的结合,加快比对速度。

    酷壳网有篇文章对rsync增量传输算法有比较详细的介绍[2]。

    rsync性能优秀且简单容易理解,作者用了两年研究出来,而使用者只用两小时就可以理解了。

    rsync工具的工作机制

    rsync增量传输算法使用最多的场景就是类UNIX系统上的rsync同步工具。该工具非常流行,被应用于大量的文件传输场景。比如现在美团点评发布系统就用rsync同步发布机器上编译后文件到生产机器上的。

    rsync工具的工作机制,如下阐述。

    目标:主机A、B,A要同步文件F-new给B,B上已有文件F-old,跟F-new相似度高。

    步骤:

    • B对文件F-old分块计算强弱摘要,链接起来生成sign文件,此过程简称sign,把sign文件发送给A;
    • A根据sign文件和本地文件F-new比较,滑动块进行差异检测,把相同块的序号和不同块的内容拼装为delta文件,此过程也简称delta,发送给B;
    • B拿到delta文件,并与本地源文件F-old结合,生成F-new文件,此过程简称patch。

    如果目标是B要同步文件给A,那就是步骤中把A、B换一下位置。

    小结:同步的双方A、B基本是对等的,一方计算sign和合并文件,一方计算delta。 双方都有较大计算量,这在一个服务器多客户端场景下,服务端压力会过大。

    zsync工具的工作机制

    zsync是Ubuntu上使用比较多的工具,主要用于分发Ubuntu的安装镜像ISO文件。zsync是rsync的一种变体,对rsync增量传输算法有所改造,并且基于HTTP协议,适合广域网应用[3]。

    zsync适用的场景是:大文件、变动少、一个分发点(服务端)、大量下载(客户端)。

    使用步骤为:

    • 发布方制作好新版系统安装ISO镜像(大文件),同时生成对应的sign文件,两者都提供HTTP下载地址;
    • 客户端如果没有旧版本镜像,那么全量下载ISO文件;
    • 客户端如果有旧版本镜像,那么下载sign文件,自己计算delta文件,同时自己合并出新版本镜像。合并过程是,发现相同块就从本地旧版本读取,不同的块,则使用HTTP Range的方式从服务端下载。

    zsync算法,使发布方(服务端)只要一次签名文件的计算即可支撑大量客户端增量下载,缓解服务端压力。需要增加的签名文件存储空间,也是成本很低的。

    云盘的文件增量同步方案

    基于上面介绍的rsync工具的传输步骤,并借鉴zsync增量下载的思路,制定云盘文件增量同步方案,如下图所示:

    增量同步-pc客户端

    增量同步-web浏览器
    主要的方案设计要点是:

    • 计算sign和计算delta都在PC客户端进行,服务器端只做必不可少的合并处理,同时客户端根据结算结果,如果发现命中率低,也可以选择全量传输;
    • 增量下载时,借鉴zsync,也把计算量放在PC客户端进行,这个实现也需要参考zsync对rsync原算法进行一定改造;
    • 浏览器处理能力有限,无法实现增量同步;
    • 服务端需要存(一定量的)sign文件、delta文件;
    • 服务端还要合并出新文件并存储,主要是基于这些考虑:
      ① 防止delta管理的复杂;
      ② 有完整文件,下载简单,浏览器下载可以直接通过mss(美团云对象存储服务,犀牛云盘的文件数据的存储工具) tempurl下载;
      ③ 增量同步出问题还可以降级服务,保证基本功能正常。

    方案还存在的问题

    1. 碎片块,这是rsync增量传输算法特点造成的,由于是滑动窗口检测,在两个相同块之间,有可能存在一个长度不定的差异块。如果相同块不连续,就会形成一系列碎片块。减少滑动块长度(也即是sign计算的固定块长度),可以提高命中率、减少碎片块,但计算量也随着加大,sign文件也变大,可能得不偿失。所以只能根据试验情况,取一个折衷的块长度。目前我们采取默认2KB的块长度,对每块生成4B弱摘要,16B强摘要,那么sign文件与源文件的长度比=20/2K=1/100(这里忽略sign文件头固定8B的小量影响)。

    2. 对JPEG、视频等类型的文件,局部改变可能性小,且文件一般比较大,差异检测计算量大但命中率低,不进行增量同步尝试。

    3. 基于以上设计方案,服务器端要做合并patch操作,但合并操作的时间和资源消耗还是挺大的,需要做:

    • 接收并缓存delta文件;
    • 从底层存储(mss)下载旧文件;
    • 合并文件;
    • 向底层存储上传新文件。

    该问题可从以下两方面做优化尝试:

    • 改进点1:合并文件流式处理,但网络的流对流处理容易不稳定。而旧文件还得全部下载,因为有随机读;
    • 改进点2:把合并过程作为异步处理,接收delta文件后,就返回给客户端“成功”,服务端慢慢合并,但如果失败了,很难有手段再重新从客户端取到正确文件,需要借助消息推送辅助。

    算法的后续优化项

    第一,rsync工具及类库中为了做到极致的最小传输量,sign文件头没有保存源文件长度,delta文件块长度用不同数量的Byte来表示。建议修改。前者保存文件长度,方便做类似zsync的改造(zsync算法起作用需要整个文件长度)和下载时的长度校验;后者用固定数量Byte表示长度(每个长度值都要使用多个Byte),虽然多消耗一些传输量,但编码简单,处理效率高。

    第二,对某些文件格式已知的文件,可以根据格式特点,做变长分块。比如MS Office的Open XML格式,其实是Zip组织方式,可以按Zip协议的分界标识来分块,提高命中率,但这需要对rsync增量传输算法进行修改。

    第三,结合CDC(content-defined chunking)做变长分块检测,这方面属于研究的方向,但目前还没有比较通用可靠的解决方案。下面根据找到的资料做一下描述:

    CDC算法是一种变长分块算法,它应用数据指纹(如Rabin指纹[5])将文件分割成长度大小不等的分块策略。与定长分块算法不同,它是基于文件内容进行数据块切分的,因此数据块大小是可变化的。算法执行过程中,CDC使用一个固定大小(如48字节)的滑动窗口对文件数据计算数据指纹。如果指纹满足某个条件,如当它的值模特定的整数等于预先设定的数时,则把窗口位置作为块的边界。

    CDC算法可能会出现病态现象,即指纹条件不能满足、块边界不能确定,导致数据块过大。实现中可以对数据块的大小进行限定,通过设定上下限来解决这种问题。CDC算法对文件内容变化不敏感,插入或删除数据只会影响到较少的数据块,其余数据块不受影响。CDC算法也有缺陷,数据块大小的确定比较困难,粒度太细则开销太大,粒度过粗则检测效果不佳。如何两者之间权衡折衷,这是一个难点。

    相比CDC,rsync是滑动块算法。滑动块算法对插入和删除问题处理非常高效,并且能够检测到比CDC更多的冗余数据,它的不足是容易产生数据碎片。如果能结合两者的优点,那就能更高效做差异检测,比如上面提到的Open XML格式按Zip标记分界的思路,其实是CDC思路的一个特例。

    参考文档

    1. Tridgell A, Mackerras, P. The rsync algorithm. The Australian National University, 1996.
    2. rsync核心算法.
    3. zsync — Optimised rsync over HTTP.
    4. Rabin指纹.
    5. 刘爱贵. 数据同步算法研究. CSDN博客.



    发现文章有错误、对内容有疑问,都可以关注美团点评技术团队微信公众号(meituantech),在后台给我们留言。我们每周会挑选出一位热心小伙伴,送上一份精美的小礼品。快来扫码关注我们吧!

    展开全文
  • 从Docker、Kubernetes入门到Kubernetes进阶实战、权限管理、日志收集、Prometheus监控告警以及持久化存储的使用,到持续集成、持续部署、流水线的设计,每一节课都是经过生产环境的考验,都可以拿来直接用在生产环境...
  • 云存储 https://www.aliyun.com/product/oss/ http://www.qiniu.com/ https://www.qcloud.com/product/cos Protobuf & json 数据序列化 https://github.com/google/protobuf Jenkins 持续集成工具 ...
  • 《iOS开发指南》(第二版 iOS7)源码

    千次下载 热门讨论 2014-03-20 11:11:59
    接下来介绍了如何实现简单表视图和分节表视图,以及表视图中索引、搜索栏和分组的使用,然后讲解了如何对表视图单元格进行删除、插入、移动等操作,最后介绍了表视图UI设计模式方面的内容。  第5章讨论了如何判断...
  • 根据内容校验和进行重复数据删除(sha512_256) (可选)压缩(zlib) (可选)使用经过身份验证加密(PBKDF2 + NaCl)进行密码保护和加密备份 MIT许可证。 支持平台:MacOS,Linux,Windows 10。 免责声明...
  • 1.6 更多关于Oracle重做日志的内容 16 1.6.1 ARCHIVELOG模式与NOARCHIVELOG模式 20 1.6.2 Oracle逻辑结构 20 1.7 组合情况 20 1.7.1 数据库的启动和关闭 21 1.7.2 使用数据库和内核 23 1.8 Oracle备份与恢复...
  • C++网络爬虫项目

    2018-07-04 00:59:17
    引擎提供商,为此开发了一整套云存储与云计算平台,使用数以万计普通PCWEBCRAWLER 网络爬虫实训项目 4 搭建了海量信息可靠存储与计算架构,以此作为搜索引擎及其相关应用基 础支撑。优秀的云存储与云计算平台...
  • 接下来介绍了如何实现简单表视图和分节表视图,以及表视图中索引、搜索栏和分组的使用,然后讲解了如何对表视图单元格进行删除、插入、移动等操作,最后介绍了表视图UI设计模式方面的内容。  第5章讨论了如何判断...
  • Xshell Plus6 v6.0.0003.zip

    2019-07-17 14:39:44
    您可以查看传输窗口以查看所有传输的进度并查看您的队列中的内容。根据需要暂停并恢复文件传输。 (5)快速安全 通过使用最大带宽使用Xftp 6来提高生产率,以便更快的文件下载/上传。利用经过验证的SSH协议进行...

空空如也

空空如也

1 2 3
收藏数 50
精华内容 20
关键字:

如何删除云存储的内容