go高级编程–分布式系统学习笔记
谷歌的chubby论文中提到: 基于强一致协议的锁适用于 粗粒度 的加锁操作, 粗粒度即占用锁时间较长的场景, 基于分布式的阻塞锁比较适合分布式任务调度场景, 但是不适合高频次的短时间抢锁操作. 比如对于秒杀系统来说, 使用redis或try-lock来做 胜者为王的操作. 而使用zookeeper/etcd就不适合这种场景, zookeeper的加锁会使得竞争者处于阻塞状态, 只有一个人成功返回. 而redis可用setnx操作使得失败者立刻返回, 胜者进入后续逻辑. 如果业务对锁的一致性要求很高,即保证锁数据的可靠性, 那么就需要使用zookeeper和etcd而不能用redis, 代价是较低的吞吐量和较高的延迟.
zk和etcd是无法通过横向扩展提高性能的, 只能增加多个集群.
定时器的实现: 时间堆(小顶堆/四叉树–go内置定时器实现) 和 时间轮(类似hash或时钟)
时间堆: 对于一个时间, 如果小于对顶则堆内定时任务都未到触发时间, 检查时间复杂度为o(1), 如果时间小于堆顶,则弹出对顶和做堆调整, 复杂度为o(lgN), 直到时间小于堆顶. 同时触发弹出任务.
时间轮: 时间每次转动到一个刻度时检查其挂载的任务是否已经到期, 每个任务分配时通过hash 触发时间%时间轮元素大小来确定挂载位置, 如果冲突就通过链表挂载进行扩展.
DSL可以表示程序的boolean表达式, json可以表示DSL, 所以json可以表示树状结构就能表示DSL就能描述程序的抽象语法树.
canal通过伪装成mysql的从库获取mysql的binlog,解析成json格式通过kafka交给下游的数据库进行分析消费或者做OLAP(数据分析)事务,下游通过写入es进行纯查询业务, 要求表中必须有唯一的主键id保证写入数据不重复, 同时通过直接覆盖id对应数据来避免了区分新增还是更新.
go 的rand.Perm是经过修正的随机洗牌算法, 使用经典的fisher-yates算法, 这个随机是伪随机. 如果需要使用真随机, 使用随机种子, rand.Seed(time.Now().UnixNano())
配置的本地缓存可以解决配置中心不可用的问题, 但是却又引入了配置文件不一致的问题,需要监控该问题. 配置中心对于大量的配置场景又需要考虑网络和存储负载. 同时配置文件的获取需要结合业务逻辑, 在业务逻辑执行时获取配置并更新配置会导致当前业务执行逻辑上的配置前后不一致. 配置的变更需要记录, 以便快速回滚.