zoukankan      html  css  js  c++  java
  • 时间戳

    时间戳的原理和意义 

    两个问题的解决 

    带宽和查询压力 

     每个 client 都会拉取一系列列表数据,典型的如好友列表、群列表、阻止列表、分组列表

    等等。这些列表数据与用户的体验密切相关,属于非常重要的数据。为了保证数据的正确拉

    取,client 最开始采取的做法是,每次登陆拉取这些列表。 

     后来我们发现用户的列表很少发生改变,于是希望 client 能够通过某种方式捕捉数据改变

    的事件,从而触发拉取动作。这么处理所带来的好处是,client 与 server 之间的流量被减少

    了,同时 server 面临的压力会被减轻。 

     我们采取的做法是为每个列表数据分配用于标识版本的时间戳。Client 在拉取列表数据之

    前,先拉取时间戳与本地时间戳进行对比,如果 server 的数据有更新,client 才会发起拉取

    操作。 

     为什么时间戳需要存放在 server 端呢?考虑如下情况: 

    机器A

    机器B Server 版本1

    版本2 Step 1

    Step 2

    Step 1 用户从机器A迁移至机器B Step 2 用户从机器B迁移至机器A 

    State 1 用户在机器 A 使用 client,然后拥有数据版本 1 作为本地存储 

    State 2 用户在机器 B 使用 client,然后操作了列表数据,拥有数据版本 2 作为本地存储 

    State 3 用户回到机器 A 使用 client,本地存储的数据版本实际上已经很低了,需要与 server

    做一次同步 

     综上所述,server 端需要为每个用户存储时间戳数据,它实际上是由多个时间戳所组成,

    每个时间戳代表着一类数据。 

     通常情况下,列表型的数据拥有自己的时间戳。此外,我们按照变化频率,把用户的属性

    数据(如签名档、头像等),分为了不同的时间戳。这里分类的依据是: 

    1. 基本不变或很少变化的数据合用一个时间戳 

    2. 变化频率较高的数据合用一个时间戳 

     对于情况 1,可以预料时间戳的版本基本不会发生变化,所以它的确可以起到节省流量的

    作用。对于情况 2,则对流量的节约作用很有限。 

    时序问题 

     对于两台服务器而言,例如 chat-dbcache: Chat dbcache R-f

    W-f

    cache

    drop

    in R-b

    W-b 数据版本发生更新

    时间 时间 

    1. R-f(read-forward)表示发出读请求 

    2. W-f(write-forward)表示发出写请求 

    3. R-b(read-backward)表示读请求处理完毕返回 

    4. W-b(write-backward)表示写请求处理完毕返回 

     由上图可知,读请求携带了一份旧数据返回给请求方(这里是 chat)。当请求方含有 cache

    时,由于没有对 cache 做额外的保护,旧数据会进入 cache。这时除了等待 cache 超时,没

    有什么好的办法把旧数据从 cache 中清除掉。 

     这个问题的本质是,对于请求方,当 write 操作返回成功之后,携带旧数据返回的 read

    操作可能入 cache,导致逻辑出现异常。这个问题的解决方案依赖于 bitmap+时间戳。首先

    介绍 bitmap,它在应用程序启动时初始化为 0: 

    Chat dbcache R-f

    W-f

    cache drop

    Can’t in R-b

    W-b 数据版本发生更新

    时间 时间

    Bitmap <- 0

    Bitmap <- 1

    client R-f2 Bitmap <- 0 1. R-f 之前,把 bitmap 置为 0 

    2. W-b 之后,把 bitmap 置为 1,然后清空 cache 

    3. 把数据加载至 cache 之前,需要检查 bitmap。如果为 0,则可以入 cache;否则不入 cache 

    第 1 点的意思是: 

    性质 1 只有 r-f 才能使 bitmap 变为 0 

    第 2 点的意思是: 

    性质 2 只有 w-b 才能使 bitmap 变为 1 

    第 3 点的意思是: 

    性质 3 只有 bitmap 为 0 时,数据才能入 cache 

    Bitmap 的引入保证了: 

    定理 1 数据入 cache 的充分必要条件是: 

    1. 没有 w-b 或者 

    2. w-b 之后有 r-f2 发出 

     充分性: 

    由性质 3,数据入 cache 可以推断 r-b 时 bitmap 为 0。由性质 2,应用程序收到 r-b 的上一

    个操作,肯定不是 w-b(因为如果是 w-b,则 bitmap 会变为 1)。 

    1) 如果 r-b 的上一个操作是 r-f,则说明没有 w-b。 

    2) 如果 r-b 的上一个操作是 r-fx,由性质 1,是否存在 w-b 不会对 bitmap 的值造成影响,

    因为即使 w-b 存在,它也一定是在 r-fx 之前被应用程序接收,那么 r-fx 发出的时候,

    一定会把 bitmap 置为 0 

    必要性: 

    1) 没有 w-b。由性质 2,bitmap 不会变为 1。则只要有 r-f 被发起,可以肯定 r-b 时 bitmap

    为 0,数据入 cache 

    2) W-b 之后有 r-f2 发出,则由性质 1,bitmap 在 r-f2 发出之后会变为 1,于是 r-b 时 bitmap

    为 0,数据入 cache 

    综上所述,命题成立。【证毕】 

     假设服务方保证: 

    性质 4 w-b 之后处理的所有 r-fx,都拥有最新版本的数据 

    那么 w-b 之后发起的 r-f2 所得到的数据一定是一份新数据。 

    Bitmap 的意义在于写操作之后,应用程序可以获得一次读数据的机会,进而获得一份新

    数据,但是 bitmap 并不能保证这份新数据,可以进入 cache 中。考虑如下情况: Chat dbcache R-f

    W-f

    cache drop

    in R-b

    W-b 数据版本发生更新

    时间 时间

    Bitmap <- 0

    Bitmap <- 1 client R-f2 Bitmap <- 0 R-b2

     

    由图可知,r-f2 的确得到了一份新数据,并在 r-b2 携带返回。然而由于 r-b 先返回,且进

    入了 cache,如果 cache 的进入是“先入为主”,那么 r-b2 无法进入 cache。 

     为了解决这个问题,再次引入时间戳的概念。假设 r-bx 携带的数据都具有一个时间戳作

    为版本的标识,那么我们可以依赖这个时间戳限制 cache 的使用,即: 

    定理 2 “高版本的 r-bx 可以进入 cache” 是 cache 中的数据不会长时间错误的充分条件。其

    中“长时间错误”的意思是,如果 cache 不超时,则数据会永远存在于 cache 中。 

     根据 bitmap 的时序图,因为高版本 r-bx 可以进入 cache,所以即使低版本 r-bx 进入 cache,

    也会被新数据淘汰。因此 cache 中的数据不会长时间错误。 

    时间戳的混乱 

    对比上述两种时间戳。为简单起见,我称它们为 A 型和 B 型时间戳。 

    A 型时间戳:解决 client-server 的流量/查询压力问题 

    B 型时间戳:配合 bitmap 解决时序问题 

     这两类时间戳的差异在于,是否关心数据内容。 

     A 型时间戳严格的表示数据的版本。对于 client 而言,为了保证功能正常,不同版本的数

    据必须对应不同版本的时间戳(否则无法获得新数据);对于 server 而言,为了保证性能,

    相同版本的数据不允许有不同版本的时间戳(否则 client 会拉取数据,从而破坏提高性能的

    初衷)。 

     B 型时间戳不需要关注它所代表的数据版本。由时序问题的背景,我们可以推断出 B 型时

    间戳只是为了解决如下问题: 

     假设有三个时间点,分别做了三件事情:r-f / w-b / r-f2,其中 

     r-f 早于 w-b 早于 r-f2 

     如何标记 r-b2 比 r-b 的数据版本新。 

     一个解决办法是,令 r-bx 的时间戳等于 r-fx 的时间戳。对于每次 r-fx,都增加 B 型时间戳的值。这么做的缺点是相同版本的数据,会在 cache 中不停的被切换;然而优点是,应用程

    序可以自己分配 B 型时间戳,不需要借助服务方的支持。 

     初看起来觉得这个做法值得推敲。但是这个解决方法可以满足定理 2,所以它是正确的: 

    1) 在没有 wb 操作的前提下,允许读操作的时序翻转。比如 r-f 和 r-f2 的时序发生了翻

    转,由于没有 wb 操作,cache 的数据一定是正确的 

    2) 存在 wb 操作的前提下,因为 r-f2 在 w-b 之后发出,那么由性质 4 可知,r-f2 一定可

    以获得一份新数据,这就表示它的数据版本一定大于或等于 r-f 的数据版本,因此可

    以使用 r-b2 替换 r-b 

  • 相关阅读:
    字符串替换
    字符串查找
    字符串比较
    字节与字符串相互转换
    1365. How Many Numbers Are Smaller Than the Current Number
    1486. XOR Operation in an Array
    1431. Kids With the Greatest Number of Candies
    1470. Shuffle the Array
    1480. Running Sum of 1d Array
    【STM32H7教程】第56章 STM32H7的DMA2D应用之刷色块,位图和Alpha混合
  • 原文地址:https://www.cnblogs.com/zxm1002/p/4741279.html
Copyright © 2011-2022 走看看