ARTS-WEEK-013
Algorithm:
15: 3Sum (Medium)
18: 4Sum (Medium)
167: Two Sum II - Input array is sorted (Easy)
一开始直接尝试4Sum一直找不到思路,看了答案才明白原来就是在3Sum基础上再循环一次,确实是比较无趣的一题。相比之下3Sum就可以用经典的双指针,排序后,用外层循环固定得到 target,后续范围进行双指针查找,根据大于小于 target 移动两个下标,注意所有循环包括移动双指针,都需要跳过重复值,以满足题目要求的无重复结果。后来想到如果 3Sum 的这一层循环再去掉,就是 167 题 Two Sum II - Input array is sorted,回过头来看这几题是一点点增加和变化的。
Review:
Linkedin: Who moved my 99th percentile latency?
这篇文章非常有特点,以分析和优化TP99为起点,通过扎实的技术基础和分析问题的方法论,找出和解决了一个隐藏在复杂分布式系统中不起眼的小问题。如果从实践总结的角度来看,就是秒级监控不足以发现网卡在毫秒级别的压力(千兆网卡100KB/ms就打满了),或更通用的说一些应用场景存在毫秒级别高并发导致其他请求延迟。
但是文章不止于解决单一问题现象,更引人深入思考了一些本质的内容。实际上优化TP99甚至TP999这类长尾延迟非常困难,分布式系统链路非常复杂,一般监控无法细化到底层系统和硬件的每一层,也无法精确到毫米级,他们通过C语言开发的UDP模拟程序、以及 tcpdump 等手段离线统计出了毫秒级延迟,非常不容易。同时也给出和应用了一个分析方法论,1受控和简单环境、2详细端到端度量、3用消除做实验、4用原型去验证。还有分析硬件资源时的公平、竞争、饥饿等因素,总之是一篇值得深入理解和学习的好文。
语言积累:Longtail latencies, root cause, microbursting traffic, hedging your bet strategy, methodology, lurking, cursory, reproduce, symptoms
This problem had been lurking for a few months with cursory investigations not showing any obvious reasons for the longtail network latencies.
Tip:
在 OpenResty 中使用 snowflake 生成唯一ID
snowflake 是著名的分布式唯一ID生成算法,通过利用毫米时间戳、自增值、worker id 进行 bit 合并构建一个 long 类型唯一 ID,在实践中一般还会根据业务需要进行 bit 分布定制、处理时钟回拨问题、处理并发溢出等健壮性问题。
在 OpenResty 中有两个第三方 snowflake 类库,第一个 lua-snowflake 是通过原生 lua 调用 C 语言实现,另一个 lua-resty-snowflake 是通过 lua-jit 的 ffi 机制调用 C 语言实现。理论上后者性能会更好,同时由于 ffi 的易用性,其 C 语言代码也更加简洁明了。
在 OpenResty 应用中首先考虑如何全局唯一,因规范约束不应使用全局变量,这里可以通过模块封装唯一对象,并用 require 引入,在模块 next_id 函数中判断使其仅初始化一次,这时考虑到 OpenResty 的整体结构: 在 nginx 的每个进程中都有独立的 lua vm,因此这是进程全局唯一。第二个应用问题是如何分配 worker id,由于进程模型,很明显每个进程唯一id的最直接选择就是 pid,此外需要再加上机器id作为datacenter id(这其实也是 worker id 的一部分),至于机器id如何分配则最好使用外部协调器如 redis 或 zookeeper 等方式,如果机器数极少甚至可以通过配置文件指定,如下面代码简单用秒数作示例:
local snowflake = require "resty.snowflake"
local ngx_worker_pid = ngx.worker.pid()
local start_sec = os.date("%S")
local _M = {
_VERSION = '0.0.1',
}
local mt = { __index = _M }
-- worker global
local sf
function _M.next_id(self)
if sf == nil then
local worker_id = ngx_worker_pid % 32
local datacenter_id = start_sec % 32
sf = snowflake:new(worker_id, datacenter_id)
end
local next_id_d = sf:next_id()
return string.format("%.0f", next_id_d)
end
return _M
参考:
https://github.com/stuartcarnie/lua-snowflake
https://github.com/KingkongWang/lua-resty-snowflake
Share:
Steve Jobs' 2005 Stanford Commencement Address
回顾经典的乔布斯斯坦福演讲,发现依然很有启发性,connect the dots、love and loss、death...