A(算法) :
    题目: 239. 滑动窗口最大值
    解法思路: 这道题目需要的代码量不大, 但是思路比较绕. 用暴力法去做很简单,时间复杂度是O(m*k).引入了window 作为队列后, 队首元素保持为window 最大值, 只有当i >= i -k 的情况下才淘汰队首元素. 优化后的算法复杂度是O(n)

    1. class Solution(object):
    2. def maxSlidingWindow(self, nums, k):
    3. """
    4. :type nums: List[int]
    5. :type k: int
    6. :rtype: List[int]
    7. """
    8. if not nums:
    9. return []
    10. window, res = [],[]
    11. #核心要义, 先清理 window, 后加入
    12. #继续拆分步骤就是 1. 保持队列头部的值是window的最大值
    13. # 2. 清理的时候,先清理头部的元素
    14. # 3. 然后清理window 队尾更小的数
    15. for i, x in enumerate(nums):
    16. if i >=k and window[0] <= i - k:
    17. window.pop(0)
    18. while window and nums[window[-1]] < x:
    19. window.pop()
    20. window.append(x)
    21. if i >= k - 1:
    22. res.append(nums[window[0]])
    23. return res

    R(Review):
    文章: 链接 Notes on Distributed Systems for Young Bloods
    总结: 这是”左耳听风” 在分布式经典材料中介绍的一篇比较简单文章, 但我觉得受益不少, 可以在日后的设计有不错的知道意义

    1. Distributed systems are different because they fail often
    2. "分布式系统跟传统系统不一样, 因为他们会经常故障": 分布式系统引入了网络因素, 这也是故障频发的最根本原因
    3. 解决的办法就是"将处理故障的代码当做正确代码的一部分" 设计系统的时候要 "design for failure"
    4. Writing robust distributed systems costs more than writing robust single-machine systems
    5. "实现一个健壮的分布式系统的代价要比单机系统高" : 如前所述, 引入了网络这个因素后, 机器之间交互的复杂性, 成本
    6. 都要比单机系统要高
    7. Robust, open source distributed systems are much less common than robust, single-machine systems.
    8. "健壮的开源分布式系统通常比开源的单机系统少见" : 我认同作者这个观点, 因为分布式系统的实现本来就比较困难, 但作者描述的情况更侧重于"开源贡献者无法持续投入", 这个理由我就觉得比较牵强, 因为无论是什么样的开源软件, 都会有这种情况出现, 跟是否分布式无直接关系.
    9. Coordination is very hard. Avoid coordinating machines wherever possible.
    10. "机器之间的协作是非常困难的, 要尽量避免" : 分布式系统会存在"两个将军", "拜占庭" 等等经典问题, 都是机器协作需要解决的问题, 然而, paxo 算法可以却解决,
    11. 要实现这个算法也不是一件容易的事情
    12. If you can fit your problem in memory, its probably trivial
    13. "如果能通过单机内存就解决的问题, 通常是个比较简单的问题": 跟之前作者的观点类似.
    14. Its slow is the hardest problem youll ever debug..
    15. ""这太慢了" 是最难定位原因的问题": 很好理解, 网络因素令到排查问题更复杂, 如果不使用全链路监控, 基本就是费时费力
    16. Implement backpressure throughout your system
    17. "在你的分布式实现 backpressure" : 我的理解是: backpressure 更像一种机制, 可以让系统感知自己所处理的流量是否已经到达上限. 从实践层面上看,就是使用限流机制来.
    18. Find ways to be partially available
    19. "保持部分可用" : 本质上就是外部资源不可控, 要有降级机制
    20. Metrics are the only way to get your job done
    21. "指标是衡量你工作是否完成的唯一标准" : 这个观点很有意思, 在单机系统, 我们通常是"输入", 然后"验证输出" 这种流程来衡量自己的代码是否已经生效
    22. 但在分布式系统中 , 必须要有指标输出, 才能判断代码是否符合自己的预期
    23. Use percentiles, not averages.
    24. "使用百分比而不是平均数来衡量系统指标" : 这算是一个常识, 平均值会淡化尖刺指标, 如一个tps 1000 的服务, 95%的 RT 5ms, 剩下的5% 2000ms, 那么这5%的尖刺就会被平均掉了.
    25. Learn to estimate your capacity.
    26. "学会评估系统的容量" : 要随时评估系统的容量是否能满足业务需求, 做好扩容计划
    27. Feature flags are how infrastructure is rolled out.
    28. "功能标记就是基础设施推进的方法" : 这个我翻译得有点别扭, 不过理解起来就是 : 在功能迭代的过程, 最好使用功能标记来小步迭代发布, 避免上线
    29. Choose id spaces wisely.
    30. "要明智地选在id 空间策略" : id 的空间策略, 其实就是要充分考虑它的扩充成本, 如果id 的生成规则没有业务含义, 那就需要引入外部系统来解决路由问题, 这样才能实现系统扩展, 如果id本身自带路由规则, 那就需要考虑这个规则会不会被破解,也就是安全性问题
    31. Exploit data-locality.
    32. "充分利用 数据本地性优势" : 很好理解, 数据能本地处理, 既可以节省带宽, 又可以降低复杂度
    33. Writing cached data back to persistent storage is bad.
    34. "将被缓存的数据回写到存储是一种不好的实践" : 其实就是要解决"数据一致性"带来的麻烦成本很高
    35. Computers can do more than you think they can.
    36. "现在的计算机能做的已经超过你想象" : 要关注硬件发展, 有时候单机的处理性能已经足够解决问题了.
    37. Use the CAP theorem to critique systems.
    38. "使用CAP 理论来评价系统" : CAP 理论虽然不能知道你如何设计系统, 但它能用来随时去评价你所做的系统. 去让你更清晰的认识到究竟在哪个部分做了trade off.
    39. Extract services.
    40. "要尽量服务化" : 作者认为, 共享逻辑通常有两个办法: 1."代码库" ,2,"服务化". 但后者是更有优势, 其原因就是可以集中式升级, 如果通过代码库共性逻辑, 就会导致这些逻辑散落到客户端, 升级起来就会比较痛苦.

    S(分享): GraphQL vs REST
    .GraphQL 是FB 公司开源的一个项目, 它主要解决以下问题.
    .传统的REST 接口只能获取单一资源, 如果要获取其关联的资源, 就需要多次去读取不同的接口.
    .比如: 想获取用户的图像和他的粉丝, 那么就需要两个步骤: 1 .获取用户信息, 2. 根据用户id 获取粉丝列表.
    .REST 接口无法灵活定制查询条件, 造成接口的冗余
    .比如: 有些页端请求需要根据查询日期来查询用户流水, 那么就需要传开始时间和结束时间作为参数(start, end). 然后它又需要根据流水状态和用户id 去查询, 那么就需要有另外一个接口需要传status , userid 参数. 如果想组合里面的参数, 可能就会需要实现更多的接口. 这样就会导致接口过度冗余.
    .GraphQL 可以通过统一的接口来满足这种需求. 网上已经有很丰富的教材, 可以直接参考 链接
    最后, GraphQL 也不是没有缺点, 他主要的缺点其实是将所有复杂逻辑移动到后端, 由于REST 接口是很简单的, 服务器很容易对其做优化(比如加缓存) , 但graphql 就比较麻烦了 ,需要定制一堆resolver 来解决这个问题, 增加了不少的复杂度. 所以在项目实施的时候要充分平衡两者的优缺点.

    T(Tips): 最近在使用maven 的时候发现了个问题, 当前我开发的是snapshot 版本的代码, 每次修改后, 即便发布了二方包 后, 本地的开发环境 intellij 也有可能无法获取最近的更), 无论”reimport” 多少次, 后来我发现不一定是intellij 的问题, 因为直接用
    mvn clean package 也是没法获取最新的包, 最简单的解决办法是直接升级版本号, 我身边的同事也是这样认为, 但我觉得这没道理啊, snapshot 本来就应该可以随时更新内容

    后来我发现解决的方法就是直接用maven 强制更新:
    使用: mvn clean package -U

    这应该是跟mvn 的代码缓存策略有关, 先记下问题, 后续再去看下它的实现原理.