菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
444
0

ARTS-WEEK-013

原创
05/13 14:22
阅读数 34102

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...

发表评论

0/200
444 点赞
0 评论
收藏