跳到主要内容

什么是科技市场接受周期中的鸿沟?

· 阅读需 5 分钟

创新是破坏性的吗?

破坏性创新(Dsruptive innovation) vs. 连续创新(Continuous innovation)

  • 它是否 ==改变我们现在的行为模式== 或者 ==改变我们依赖的其他产品和服务==。
  • 在连续创新和不连续创新之间,存在着对行为改变的一系列需求。

高科技公司经常引入一些破坏性创新。在这些破坏性创新的过程中,人们成为了这些产品的用户。这种转变通常是以正态分布的形式发生,所以这些产品的用户增长成S曲线。

什么时候人们会购买高科技产品?

科技应用的生命周期

在==科技应用的生命周期==中,人们在不同阶段成为了破坏性创新产品的用户。他们是:

  1. 创造者(Innovators)
  2. 早期接受者(Early adopters)
  3. 大部分早期用户(Early majority 实用派)
  4. 大部分晚期用户(Late majority 保守派)
  5. 落后者

什么是高科技市场模型?

这个周期为==高科技市场模型==提供了指导,==如何发展一个高科技市场,就是让这个周期顺利的从左到右进行,一个一个用户群体,逐个突破。== 借着左边的用户群体的浪潮更容易向右边的用户群体推销产品。

用户浪潮是很重要的,因为它能

  1. 节约成本
  2. 如果你不想在下一次破坏性创新或者竞争者面前错过机会,这会让周期推进得更快

鸿沟在哪里?

观察科技应用的生命周期,我们可以看到 跨过断层

  • 两处裂缝

    1. 在创造者和早期接受者之间存在一个裂缝,即合适的应用场景。例如 Esperanto, VRML, second life, 3D打印。 要跨越这个裂缝,我们需要一个标志性的产品。
    2. 在大部分早期用户和大部分晚期用户之间存在另一个裂缝,即有竞争力的产品。例如 home automation.scanning 和项目管理软件. 要跨越这个裂缝,我们需要让产品更容易被人接受。
  • 和一个断层

    1. 早期接受者到大部分早期用户的断层。因为他们的需求是不一样的:

      1. 早期接受者想要的是一个改变 -- 他们期望能在竞争市场上得到一个飞跃。产品上有些小问题没有关系。
      2. 以实用主义者为主的大部分早期用户想要的是生产效率的提高。他们想要科技去==提高,而不是颠覆他们做事的基本方式==。
    2. 前两个阶段的人和后面两个阶段人的不兼容

      1. 早期接受者的行为对于大部分早期用户来说不是一个很好的参考。
      2. 而且因为大部分早期用户不想破坏他们已有的组织架构。一个好的参考对他们要不要用这个产品的决定是非常重要的。
    3. 谁真的在2014年遇到过这个断层?例如 holograms, pen-based tablets, fuel cells, 二维码(在美国), 大部分在线课程, Segways, Motorola iridium.

Netflix 如何提供观看数据?

· 阅读需 2 分钟

动机

如何在规模上保持用户的观看数据(每天数十亿事件)?

在这里,观看数据指的是...

  1. 观看历史。我看过哪些标题?
  2. 观看进度。我在某个标题中停留在哪里?
  3. 正在观看的内容。我的账户现在还在观看什么?

架构

Netflix 观看数据架构

观看服务有两个层次:

  1. 有状态层 = 活动视图存储在内存中

    • 为什么?为了支持最高的读/写量
    • 如何扩展?
      • 按照 account_id mod N 分区为 N 个有状态节点
        • 一个问题是负载分布不均,因此系统容易出现热点
      • CAP 定理 下选择 CP 而非 AP,并且没有活动状态的副本。
        • 一个失败的节点将影响 1/n 的成员。因此,他们使用过时的数据以优雅地降级。
  2. 无状态层 = 数据持久性 = Cassandra + Memcached

    • 使用 Cassandra 进行非常高的写入量和低延迟。
      • 数据均匀分布。由于使用虚拟节点进行一致性哈希来分区数据,因此没有热点。
    • 使用 Memcached 进行非常高的读取量和低延迟。
      • 如何更新缓存?
        • 在写入 Cassandra 后,将更新的数据写回 Memcached
        • 最终一致性,以处理多个写入者,具有短的缓存条目 TTL 和定期的缓存刷新。
      • 将来,优先考虑 Redis 的追加操作到时间排序列表,而不是 Memcached 中的“读-修改-写”。

如何设计健壮且可预测的 API 以实现幂等性?

· 阅读需 3 分钟

API 如何可能不够健壮且不可预测?

  1. 网络不可靠。
  2. 服务器更可靠,但仍可能出现故障。

如何解决这个问题?三个原则:

  1. 客户端重试以确保一致性。

  2. 使用幂等性和幂等性键进行重试,以允许客户端传递唯一值。

    1. 在 RESTful API 中,PUT 和 DELETE 动词是幂等的。
    2. 然而,POST 可能导致==“双重收费”问题==。因此,我们使用==幂等性键==来识别请求。
      1. 如果故障发生在服务器之前,则会进行重试,服务器将首次看到该请求,并正常处理。
      2. 如果故障发生在服务器中,则 ACID 数据库将通过幂等性键保证事务。
      3. 如果故障发生在服务器回复之后,则客户端重试,服务器简单地回复成功操作的缓存结果。
  3. 使用==指数退避和随机抖动==进行重试。要考虑==雷鸣般的群体问题==,即服务器可能处于降级状态,突发的重试可能会进一步损害系统。

例如,Stripe 的客户端重试计算延迟如下...

def self.sleep_time(retry_count)
# 根据到目前为止的尝试次数应用初始网络重试延迟的指数退避。不要让这个数字超过最大网络重试延迟。
sleep_seconds = [Stripe.initial_network_retry_delay * (2 ** (retry_count - 1)), Stripe.max_network_retry_delay].min

# 通过在 (sleep_seconds / 2) 到 (sleep_seconds) 范围内随机化值来应用一些抖动。
sleep_seconds = sleep_seconds * (0.5 * (1 + rand()))

# 但永远不要少于基础睡眠秒数。
sleep_seconds = [Stripe.initial_network_retry_delay, sleep_seconds].max

sleep_seconds
end

如何使用幂等性设计出高可靠的API?

· 阅读需 2 分钟

为什么API会不可靠?

  1. 网络会出错
  2. 服务器会出错

怎么解决这个问题呢?三个原则

  1. 客户端用“重试”来保证状态的一致性

  2. 重试的请求里要有==幂等的唯一性ID==

    1. 在 RESTful API 设计里面,PUT 和 DELETE 的语义本身是幂等的
    2. 但是 POST 在在线支付领域可能会导致==“重复付两次钱”的问题==,所以我们用“幂等的唯一性ID”来识别某个请求是否被发了多次
      1. 如果错误发生在到达服务器之前,重试过后,服务器第一次见到它,正常处理
      2. 如果错误发生在服务器,基于这个“唯一性ID”,用 ACID 的数据库保证这个事务只发生一次
      3. 如果错误发生在服务器返回结果之后,重试过后,服务器只需要返回缓存过的成功的结果
  3. 重试要负责任,比如遵循==指数退避算法==,因为不希望一大波客户端同时重试。

举个例子,Stripe 的客户端是这样计算重试的等待时间的:

def self.sleep_time(retry_count)
# Apply exponential backoff with initial_network_retry_delay on the
# number of attempts so far as inputs. Do not allow the number to exceed
# max_network_retry_delay.
sleep_seconds = [Stripe.initial_network_retry_delay * (2 ** (retry_count - 1)), Stripe.max_network_retry_delay].min

# Apply some jitter by randomizing the value in the range of (sleep_seconds
# / 2) to (sleep_seconds).
sleep_seconds = sleep_seconds * (0.5 * (1 + rand()))

# But never sleep less than the base sleep seconds.
sleep_seconds = [Stripe.initial_network_retry_delay, sleep_seconds].max

sleep_seconds
end

如何扩展网络服务?

· 阅读需 2 分钟

AKF 规模立方体将扩展过程可视化为三个维度…

AKF 规模立方体

  1. ==水平复制== 和克隆 (X 轴)。在负载均衡器或反向代理后面拥有一组相同且最好是无状态的实例。因此,每个请求都可以由这些主机中的任何一个来处理,并且不会有单点故障。
  2. ==功能分解== 和分段 - 微服务 (Y 轴)。例如,身份验证服务、用户资料服务、照片服务等。
  3. ==水平数据分区== - 分片 (Z 轴)。将整个堆栈复制到不同的“集群”。每个集群可以针对特定的大用户群。例如,Uber 在中国和美国都有数据中心。每个数据中心可能会有不同区域的“集群”。

想要一个例子吗?去看看 Facebook 如何扩展其社交图谱数据存储

如何构建大规模的网站服务?

· 阅读需 1 分钟

==一个字:拆==

==AKF扩展立方==告诉了我们"拆"的三个纬度:

AKF Scale Cube

  1. ==水平扩展== 把很多无状态的服务器放在负载均衡器或者反向代理的后面,这样每个请求都能被其中任意一个服务器受理,就不会有单点故障了。
  2. ==业务拆分== 典型的按照功能分的微服务,比如 auth service, user profile service, photo service, etc
  3. ==数据分割== 分割出整套技术栈和数据存储专门给特定的一大组用户,比如优步有中国和美国的数据中心,每个数据中心内部有不同的 Pod 给不同的城市或地区。

为什么导师无法帮助你晋升?

· 阅读需 2 分钟

研究发现

  1. 成功的白人男性获得的职业指导比女性和多元文化专业人士更多。
  2. 拥有导师的女性比男性多,但获得晋升的女性却更少。

为什么?==导师无法帮助晋升,而赞助人可以==。

什么是赞助人?

赞助人是

  • ==投资者和受益人==。赞助人是对被赞助者的职业成功有投资的高级员工。
  • ==直接影响你晋升的人==。赞助人直接推动被赞助者的晋升,利用他们的影响力和网络将他们与高管任务、重要人物、薪资增加和晋升联系起来。
  • ==资源分享者==。赞助人将他们的活跃网络连接分享给被赞助者,并为他们建立新的联系。
  • ==放大器==。赞助人为被赞助者的可见性助力,常常利用他们自己的平台和声誉作为曝光的媒介。

谁可以成为赞助人?

  1. 谁做出影响你/你的员工薪资、晋升或项目分配的决定?
  2. 哪些高级领导可以从你/你的员工的职业发展中受益?
  3. 哪位高级领导拥有最能帮助你/你的员工在职业上发展的网络或平台?

为什么职业导师(mentors)没法帮你升职?

· 阅读需 2 分钟

研究发现

  1. 成功的白男们会比女性和来自其他文化背景的专业人士接受更多的职业指导。
  2. 女性比男性有更多的职业导师,但是女性比男性升职的更少。

为什么?==因为职业导师(mentor)没法帮助你升职,而职业赞助人(sponsor)可以==。

什么是职业赞助人?

赞助人是...

  • ==你职业的投资者和受益者==。他是更高级别的雇员,能够投资你的职业发展,并能从中获利。
  • ==你升迁的直接影响者==。他能够直接给你升职,或者动用他影响力直接帮你升职。
  • ==资源的分享者==。他能够分享他的关系网络资源帮助你。
  • ==放大器==。他能够动用他的平台和名声帮你放大你在公司的可见度(visibility)。

谁是你的职业赞助人?

  1. 谁发钱?谁决定升职?谁决定项目怎么分配?
  2. 哪位领导能够从你的职业成就中获利?
  3. 哪位领导的关系网络和平台能够帮你或者你的下属升职?

如何通过 HTTP 为移动设备流式传输视频?HTTP 实时流媒体 (HLS)

· 阅读需 2 分钟

动机

移动设备上的 HTTP 实时流媒体视频服务,...

  1. ==内存/存储有限==
  2. 遭受不稳定的网络连接和可变带宽的影响,并需要 ==中途质量调整。==

解决方案

  1. 服务器端:在典型配置中,硬件编码器接收音视频输入,将其编码为 H.264 视频和 AAC 音频,并以 MPEG-2 传输流的形式输出。

    1. 然后,流被软件流分段器分解为一系列短媒体文件(.ts 可能为 10 秒)。
    2. 分段器还创建并维护一个索引(.m3u8)文件,其中包含媒体文件的列表。
    3. 媒体文件和索引文件都发布在网络服务器上。
  2. 客户端:客户端读取索引,然后按顺序请求列出的媒体文件,并在段之间无任何暂停或间隙地显示它们。

架构

HLS 架构

键值缓存有哪些用法?

· 阅读需 3 分钟

KV Cache的本质是为了减少访问数据的延迟。比如,把存在又贵又慢的媒体上的数据库的O(logN)的读写和复杂的查询,变成存在又快又贵的媒体上的 O(1)的读写。cache 的设计有很多策略,常见的有 read-through/write-through(or write-back) 和 cache aside.

常见的互联网服务读写比是 100:1 到 1000:1,我们常常对读做优化。

在分布式系统中,这些 pattern 的组合都是 consistency, availability, partition tolerance 之间的 trade-off,要根据你的业务需求具体 选择。

一般的策略

    • Read-through: clients 和 databases 之间加一层 cache layer,clients 不直接访问数据库,clients 通过 cache 间接访问数据库。 读的时候 cache 里面没有东西则从database更新再返回,有则直接返回。
    • Write-through: clients 先写数据到 cache,cache 更新 database,只有 database 最终更新了,操作才算完成。
    • write-behind/Write-back: clients 先写数据到 cache,先返回。回头将 cache 异步更新到 database. 一般来讲 write-back 是最快的
    • Write-around: client 写的时候绕过 cache 直接写数据库。

cache aside pattern

Cache 不支持 read-through 和 write-through/write-behind 的时候用 Cache aside pattern

读数据? 命中 cache 读 cache,没命中 cache 读 database 存 cache 改数据? 先改 database,后删除 cache entry

为什么不是写完数据库后更新缓存?主要是怕两个并发的 database 写操作导致两个并发的 cache 更新导致脏数据。

是不是Cache Aside这个就不会有并发问题了?还是有很低的概率有可能发生脏数据,就是一边读 database 并更新 cache 的时候,一边更新 database 并删除 cache entry

缓存放在哪?

  • client side,
  • distinct layer
  • server side

缓存大小不够用的话怎么办?缓存回收策略(cache replacement policies)

  • LRU - least-recently used 看时间,只保留最近时间使用的,回收最近时间没使用的
  • LFU - least-frequently used 看次数,只保留使用次数最多的,回收使用次数最少的
  • ARC 性能比LRU好,大致做法是既保持 RU,又保持 FU,还记录了最近回收的历史。

缓存用起来谁家强?

Facebook TAO