乌兰察布之旅

上周末和朋友一起去了乌兰察布,广袤的草原和火山,整个景色给人的感觉很空旷,让人很放松,工作久了出来转一转还不错。我们游玩的顺序是:乌兰哈达的 5 号火山 -> 2 号火山 -> Day2 -> 黄花谷,整个旅程中除了在路上花费了一些时间外,体验还是不错的。

在下面还有一些拍的视频。

编程|做合适的系统设计

我一直觉得编程就像走迷宫,当我们把程序功能都跑起来,说明前人已经把这些路都探索走过了;当我们把一个功能开发测试完毕发布,就像从乌漆麻黑的草丛里穿过,最终看到光明;当程序出现一些问题,我们根据自己的经验排查链路、debug 代码仿佛又一头扎进伸手不见五指的迷雾。

归根到底,这些是系统设计和编码规范的问题。系统设计是难的,需要不断权衡,同时可能会让人陷入邪恶的设计循环,导致复杂的设计;编写代码的人不同,导致代码不易理解;另一个很重要的因素是时间,时间会让人遗忘,并且人对代码的认知会随着时间的推移改变。

摘|具有适应性的复杂系统

当我们说一个组织是一个具有适应性的复杂系统时,我们指的是:

  • 它包含许多相互依赖的部分(比如人员、技术、流程、文化等)。
  • 各个部分可以自行改变自己的行为,并适应系统的变化。

宇宙中充满了这类的系统,而且关于复杂性的研究已成为一门成熟的科学学科。 就连你自己也是一个具有适应性的复杂系统。你可能认为自己是一个单元(即一个自我),但是“自我”只是一种抽象。实际上,你是有机细胞的集合,尽管这个细胞集合拥有许多惊人的能力:思考、移动、感知,并作为一个全新的整体对外部做出反应。从细胞的角度来说,你的每个细胞都有专门的作用,细胞会进行新陈代谢,细胞群通过协同工作对你的身体产生巨大的影响。你体内生物系统的复杂性使得你的身体具有高度的弹性和适应性。虽然你不能长生不老,但由于体内复杂的生物系统,你仍然可以承受巨大的环境变化,甚至是人身伤害。

Java|进度条工具

有时候批量处理任务无法观察执行情况,例如处理进度、处理数量、耗时等,这种“不确定性”会隐藏 bug,等到出问题就晚了。今天,这篇文章的“主角” —— 进度条工具 —— 就是为了解决这个问题。

进度条工具输出预览:

 1[4B645A43] 远程请求记录: [####                ] - 22.91% (9835/42920), 耗时: 2m32s
 2   (1)        (2)               (3)               (4)       (5)          (6)
 3
 4各部分说明:
 5
 6(1) Trace ID
 7(2) 进度条名称
 8(3) 进度条面板
 9(4) 执行占比
10(5) 执行数量细节
11(6) 执行耗时

春暖花开好时节

视频,阅读全文查看。

读《Google 软件工程》

image

Software Engineering at Google》。

这本书从三个角度说明了软件工程是什么,分别是:时间、规模、权衡。时间应该是软件工程中最大的变量,随着时间推移新需求会出现,框架和库会升级打补丁,而原先的产品设计、服务端的算法、机器资源可能已经不再适合,这些变化需要维护,如何应对解决这些问题呢?当产品及业务扩大时,对应资源开销也会逐渐增大,资源包括人力和硬件资源(内存、CPU、存储、带宽),当这些规模不断增大如何保障相应的效率、成本?当面临这些问题时,往往不止一个方案,没有银弹,我们需要权衡利弊然后再再行动。在软件开发中会遇到许多诸如以上的问题,从这个角度可以窥探软件工程一些细节。

一次简单的SQL优化带来的性能提升

最近在大数据平写 Hive SQL 跑离线作业,数据量大概在三千万,有一个离线任务每次执行都要两个小时以上,我感觉太慢了。为什么觉得慢?刨除实现 SQL 逻辑的时间,自测、冒烟测试、上线每次执行一次需要 2h,也就是修改一处 SQL 要经历 6 小时才能看到最终结果。根据我的经验判断不应该耗费这么长时间,于是想着看看能不能改善一下。我先让数据平台的同学帮忙看,由于他们忙没得到结果,于是自己动手优化了一下,优化后的结果还是比较让我吃惊的,因为我并没有使用很复杂高深的手段(主要是减少临时表、减少嵌套查询数),却得到了意向不到的效果。这使我产生许多想法和思考。

优化后的效果:时间减少 95%,内存减少 80%。

  • 优化前:耗时 2h,内存占用 80G
  • 优化后:耗时 6min,内存占用 16G

总结

  1. 这次SQL优化并不复杂却带来了可观的性能收益,说明简单的理论基础和参数调整也能达到不错的性能,仅仅一点点变化性能就可能差一个数量级;

  2. 熟悉理论基础和计算机原理,是写出高效的程序必要条件;

随笔|飞向外太空

好久不见

前段时间,我和实验室的同学开了一次线上会议。我们这届实验室自 22 年年底以来还没怎么聚,大家进入视频会议都有些兴奋。一句“好久不见”点燃了埋藏在心底的情感,“是呀,好久不见了~”。这次会议我印象深刻的有两点。第一个是当我们讨论其中一个主题时,有些同学不怎么发言,远远鼓励大家理性说出自己的观点并表示允许尖锐的声音。她随后解释:“一个积极正向发展的团队,是同时需要温和的声音和尖锐的声音的。尖锐不代表错,而一味地温和可能是在隐藏问题。”,我很赞同她的这个观点,相信好的团队能自己消化问题,形成良性循环。第二个是一个问大家的问题:“工作后你的目标变化了吗?”,大家犹豫了一下,每个人都说了一些,但又好像没有说到重点,我发言时说:“变了一些”,从工作以来我越来越觉得自己之前话有些狂妄和异想天开,在开发中,编程语言是简单的,然而业务是复杂的!即使一个简单的登录认证功能在企业环境里也可能很复杂。


从摄影学到的

在我买相机的几个月拍了一些照片,起初我在网上看了些教程,学到了些伎俩,但拍出的照片让人满意的不多,一组照片只有几个,有时甚至一个也没有,这不禁让我陷入自我怀疑:是我设备不行还是技术不到家?这种情况直到我开始主动思考相机运作机制和每个参数配置的含义后才有所改善,拍不好、不出片是因为不熟悉工具,还有是部分教程看似有用实则无用。现在,如果一个新手问我怎么学摄影,我会告诉他先把工具用熟,了解每一个配置对画面的影响,通过实践形成对光影和环境处理的认知,最后再学习构图知识。


理性、感性

两周前跟朋友一起出去拍照,我问了他一个问题:“你认为摄影是理性的还是感性的?”,朋友可能也没有思考过这个问题,随口回了我一句:”随性的,喜欢的事物,心里有拍照的冲动就按快门“。我倾向于摄影是理性的,每当我们按下快门心里都会对周围环境做一个判断,然后决定用多大光圈、快门,我们也会主动选择一个角度呈现这个画面,即使当我们希望画面呈现出感性时也是心智做出的一个选择(配置参数、控制画面)。

使用多线程的实践思考

image

本文源自一个线上问题引起的思考。诚然多线程是有益的,但使用不当反而会造成系统吞吐能力下降,甚至发生死锁。在使用多线程时我们可能面临下列情况:

  1. 当写的并发代码包含框架类的方法调用,总是可能存在线程安全问题,因为框架在不停升级,我们不能保证它一直线程安全的;
  2. 线程配置不当会引起安全问题,例如:缓存队列溢出、瞬时任务增多导致线程池打满,我们的业务在不断变化,在一个新的上下文环境中,没有人能保证线程配置一直合理;
  3. 多线程让编程更复杂(需要处理更多情况),例如:控制执行顺序、并发访问变量;
  4. 在多线程中进行远程请求容易对下游服务(数据库服务或其他业务服务)造成压力;

通过以上,我们看到在项目中引入一种技术带来的额外风险,有时这种风险不是线性增长而是指数级别,因此从这些角度看应该谨慎使用多线程。好的实践是先寻找其他解决方案,最后再考虑使用多线程,把多线程当作性能扩展的最后一道防线。

如果不用多线程就不存在上述的问题,我们假设使用多线程背景下来总一些实践技巧。

MySQL 的字符集与排序规则

通俗讲字符集就是字符码的集合,在 MySQL 中字符集的选择影响字符码的存储,字符集选择不好不仅影响存储展示还会有问题,例如乱码。

在业务中常用的字符集是 UTF-8 字符集,mysql 有两种这样的字符集:utf8、utf8mb4,它们的区别如下:

  • utf8: 支持最长 3 Byte 的字符编码,但一部分 UTF-8的 4 Byte 编码不支持,例如 emoji。
  • utf8mb4:支持最长 4 Byte 的字符编码。这是业务中使用最多的字符集,从 MySQL 8.0 开始成为默认字符集。

字符的排序规则(collate):字符在比较、排序时以及大小写敏感的规则。涉及字符比较的操作均与其相关,例如:排序、分组、索引、比较(=、>、<等)。MySQL 中有些字符排序规则是忽略大小写的,例如 utf8mb4_general_ci 排序规则,这种带有 ci 后缀的是大小写不敏感的标志(ci 即 case insensitive 的缩写)。