PingCAP CTO 黄东旭:如何做出让人爱不释手的基础软件( 三 )


故事的真假暂且不聊 , 假设是真的 , 我们可以看到直觉和经验 , 真的是能产生很多的价值 , 我当时听到这个故事的第一反应是 , 这个老师傅肯定这种情况见的多了(废话) , 而且这个问题一定是常见问题 。
其实解决问题最难部分是通过观察(尤其是一些特征点)排除掉绝大多数不靠谱的方向 , 另外要相信常见故障的原因是会收敛的 。 这时一个具有良好可观测性系统的第一步就是能给使用者的直觉指引方向 , 这个方向就需要前人的知识来给出可能性最大的故障点以及相关的指标(例如CPU使用率等);第二步就是通过一些心理学小技巧把它展现出来 。
下面以TiDB中即将会引入的一个小功能TopSQL加以佐证 。 这个功能说起来也很简单 , 我们发现很多用户故障都和少量的SQL相关 , 这类的SQL的特征是拥有和别的SQL有明显不同的CPUfootprint , 但是每一条SQL的footprint独立看起来还挺正常的 , 所以TopSQL的功能就是回答:CPU到底消耗了多少?在哪些SQL上?我试着不去解读下面这个截图 , 我猜聪明的你马上就能知道怎么用:
PingCAP CTO 黄东旭:如何做出让人爱不释手的基础软件
文章图片
你的直觉会告诉你 , 后半段那段密集的绿色占比好像和其他有什么不一样 , 将整体的CPU使用率推高了 , 感觉有问题的样子 , 没错 , 这大概就是正确的方向 , 好的可视化能够利用人的直觉快速定位主要矛盾 。
5、什么叫做“一个操作”?识别操作的真正的生命周期
刚才写第一点的时候想到还有一个经常被人忽略的关键资源:时间 。 本来想把时间放到关键资源那节里面 , 但是想了想放在这里可能更加合适 。
稍微形而上一点来看 , 我们现在的计算机都是图灵机的实现 , 我小学就知道图灵完备语言的最小功能集合:读/写变量 , 分支 , 循环 。 用文学一点的说法是:所谓程序就是无数个轮回 , 大轮回嵌套着小轮回(循环) , 每个轮回中根据现状(变量)不断的做出选择(分支) 。
我说到这里可能聪明的读者会猜到我想说什么:如果我们讨论可观测性脱离了周期 , 就毫无意义 。 而周期的定义又是灵活的 , 对于人而言 , 大周期显然是一辈子 , 小周期可以是一年一日 , 甚至周期可以不用时间跨度作为单位 , 比如一份工作的周期…
对于一个数据库软件而言 , 什么是一个合理的周期?是一条SQL的执行周期?还是一个事务从Begin到Commit?这里没有标准答案 , 但是我个人建议 , 周期越贴近终端用户的使用场景越实用 。
譬如 , 在数据库中 , 选择单条SQL的执行作为周期不如选择事务的周期 , 事务周期不如应用程序一个请求全链路的周期 。 其实TiDB在很早就引入了OpenTracing来追踪一个SQL的执行周期内到底调用了哪些函数 , 花费多少时间 , 但最早只应用在了TiDB的SQL层内部(熟悉我们的朋友应该知道我们的SQL和存储是分离的) , 没有在存储层TiKV实现 , 所以就会出现一条SQL语句的执行过程往下追到TiKV就到了一个断头路;
后来我们实现了把TraceID和SpanID传到了TiKV内部这个功能才算初步可用 , 至少把一个周期的图景变得更加完整了 , 本来我们打算就止步于此 , 但是后来发生了一个小事情 , 某天一个客户说:为什么我的应用访问TiDB那么慢?然后我一看TiDB的监控 , 没有啊 , SQL到数据库这边基本都是毫秒就返回了 , 但是客户说:你看我这个请求也没干别的呀 , 两边怎么对不上?后来我们把Tracer加进来以后才知道客户这边的网络出了点问题 。
这个案例提醒了我 , 如果能做到全链路的Tracing , 这里的全链路应该是从业务端请求开始计算 , 去看待生命周期才有意义 。 所以在此之后我们在TiDB里面通过拓展SessionVariable , 能够支持用户将OpenTracing协议的Tracer信息通过SessionVarible传入到TiDB的体系中 , 打通业务层和数据库层 , 能够真正实现的一个全生命周期的跟踪 , 这个功能也会在很近的未来的版本中和大家见面 。