把服务实例存成 etcd 的一个前缀目录,实例多了查询要多久?分页怎么保证一致?频繁更新会让数据库涨多大?compaction 和 defrag 各做什么?这篇用 10 万个 key 的前缀量出来。
key 数 | 完整查询 | keys_only | count_only | limit 100 | 完整 + serializable --------+----------------------------+--------------------------+--------------------+---------------------+--------------------------- 1,000 | 3.9 ms(3.0) · 358 KB | 1.7 ms(1.3) · 84 KB | 0.5 ms(0.5) · 0 KB | 0.7 ms(0.6) · 36 KB | 3.7 ms(2.9) · 358 KB 10,000 | 30.8 ms(23.2) · 3592 KB | 14.0 ms(9.8) · 858 KB | 0.5 ms(0.5) · 0 KB | 0.8 ms(0.7) · 36 KB | 31.0 ms(22.9) · 3592 KB 100,000 | 318.1 ms(225.4) · 36107 KB | 139.2 ms(94.1) · 8763 KB | 2.1 ms(2.1) · 0 KB | 2.1 ms(2.0) · 36 KB | 310.4 ms(217.5) · 36107 KB 完整查询的代价随 key 数线性增长,而且响应是 base64 编码的 JSON,体积比原始数据大;keys_only 省掉 value,count_only 只返回个数,limit 100 只取 100 条,代价几乎不随 N 增长。服务发现的客户端每次变化都全量查询的话,实例数一大就很贵,应该首次全量加 watch 增量
完整查询随 key 数线性增长;limit、count_only 几乎不随 N 增长。
读法 | 读到的 key 数 | 请求数 | 总用时 | 扫描期间的写入数 | 读到的、版本比“第一页读取时的 revision”还新的 key 数 -------------------------+-----------+-----+--------+----------+----------------------------------- (a) 一次完整查询 | 100000 | 1 | 0.32 s | 14 | 0 (b) 每页 1000,不固定 revision | 100000 | 100 | 0.50 s | 31 | 27 (c) 每页 1000,固定 revision | 100000 | 100 | 0.50 s | 30 | 0 一次完整查询是一个一致的快照,但响应很大;分页不固定 revision 时,各页读自不同的时刻,读到的是混合了新旧版本的视图;固定 revision 的分页每一页都读同一个快照,代价是该 revision 不能被 compaction 压缩掉
分页不固定 revision 读到新旧混合的视图;固定 revision 得到一致的快照。
阶段 | dbSize(文件大小) | dbSizeInUse(实际在用) ------------------------+--------------+------------------ 初始(5000 个 key 各写一次之后) | 30.0 MB | 30.0 MB 更新 20 轮(10 万次写入)之后 | 59.0 MB | 59.0 MB compact 到当前 revision 之后 | 59.8 MB | 30.5 MB defrag 之后 | 30.5 MB | 30.4 MB 每次更新都会产生一个新 revision,旧版本留在数据库里;compaction 把旧版本标记为可回收,但文件不会变小(dbSize 不变,dbSizeInUse 变小);defrag 才真正把空闲页还给文件系统。服务注册这类频繁续约、更新的场景,不定期 compaction 和 defrag,数据库会一直长大
更新留下旧版本;compaction 回收但不缩小文件,defrag 才缩小。