背景
最近在开发自研日志平台的日志采集agent。这里记录下高可用设计的一些思考和技术细节。
当遇到发送到下游失败需要重试的场景。我们如何合理设计重试?如何优雅重试呢?
首先,我们需要明确重试的本质是什么?
重试的本质
重试的本质是我们认为这个故障是暂时的,而不是永久的,所以我们会去重试
因此,我们需要清晰的定义什么情况下需要重试,什么情况下重试是没有意义的
最近在开发自研日志平台的日志采集agent。这里记录下高可用设计的一些思考和技术细节。
当遇到发送到下游失败需要重试的场景。我们如何合理设计重试?如何优雅重试呢?
首先,我们需要明确重试的本质是什么?
重试的本质是我们认为这个故障是暂时的,而不是永久的,所以我们会去重试
因此,我们需要清晰的定义什么情况下需要重试,什么情况下重试是没有意义的
分享我参与严选技术工作组的日志平台项目中的时候,在日志收集agent这块遇到的一些问题,深入到每个底层细节和大家谈谈。
日志agent对于使用日志平台的用户来说,是一个黑盒。对于用户来说,agent有些不好的地方:
所以我觉得日志收集agent对大家来说是一个阴暗潮湿的地底世界:
就让我举起火把,照亮所有dark、dirty、creepy的地方。
程序员的自我修养
这里主要和大家分享我在开发DQC(数据质量中心)的过程中,对产品需求、架构设计、编码、自我提升这4个环节的反思与经验。
产品需求阶段,我们能做什么,该做些什么?
我认为有2点很重要:
那如何做到这2点呢?我认为有个非常重要的概念:领域通用语言
之前开发的分布式唯一id比较简陋。这段时间重新设计优化,变成一个独立的项目X-UID。这里记录下设计优化的一些东西
基本算法还是基于snowflake。因为需求就是要一个long型数字,snowflake算法简单高效。
算法生成的id结构图:
说明:
类似mysql等数据库偏爱用b+tree这个数据结构作为索引,这是为什么呢?要解释这个原因,必须先讲下计算机组成原理中的磁盘数据存取原理。
这里指普通的机械磁盘。
先看下磁盘的结构:
优化前,写入速度平均3000条/s,一遇到压测,写入速度骤降,甚至es直接频率gc、oom等;优化后,写入速度平均8000条/s,遇到压测,能在压测结束后30分钟内消化完数据,各项指标回归正常。
年前在v2ex遇到阿里中间件的哥们,内推面试。从2018.02.01开始到今天2018.03.20,一场浩浩荡荡,跨年,持续了1个半月时间的残酷面试终于尘埃落定。遗憾的未能加入阿里中间件部门这个大家庭,让我深感痛惜。
最终未能如愿的原因是“名额有限,有更适合的同学”。这也可能是内推大哥为了顾及我的感受的说辞,可能是最后一面面的不好。
这里凭借隐约的记忆,总结下面试经过。让我自己引以为戒,奋发自强,继续前行
公司使用基于redis setNX的分布式锁偶现失效,对此深入研究一番
大体来说,分布式锁的场景有两种:
为什么强调单节点?因为我们就一个redis主从,没有redis集群。而且redis有官方的分布式锁redlock是基于redis集群的,这个对我们不适用,而且感觉有点过重。
我们一开始的方案是基于setNX(key,value,timeout)。后来发现原来这是jedis的封装,这其实是2个redis命令:setnx+expire
。也就是说这不是个原子操作,很可能setnx成功,但是设置过期时间失败导致锁永远无法释放
翻看redlock的套路才知道,应该这样操作:
获取锁:set key randomValue NX PX 3000
redis的set操作有NX(if not exist)选项和PX(过期时间)选项,可以实现原子操作
释放锁:需要使用LUA脚本实现复合操作的原子性:
|
|
基于rocketmq 4.2.0
先不关注顺序消息和事务消息,后面独立看。
DefaultMQProducer#send(Message)
默认的是同步发送。最终调用的是DefaultMQProducerImpl#sendDefaultImpl
,直接看代码:
|
|
之前开发分布式追踪系统x-apm的时候,确认了2个目标:
针对第2点,用来暂存追踪数据的数据结构碰到了伪共享的问题,导致收集发送的效率不够高,所以使用的缓存行填充。
这里记录下伪共享和缓存行填充的相关内容。
一个典型的cpu cache架构:
访问速度:寄存器<L1 cache<L2 cache<L3 cache<主存
所以,充分利用它的结构和机制,可以有效的提高程序的性能
这里需要注意:一个cpu中的多核共享L3 cache,而L1、L2 cache是每个核心各自拥有的;一个缓存行一般缓存64byte大小的数据