在线上环境运维过程中,我们通常需要治理慢查询的风险。慢查询会引起DB性能问题,并且当线上环境流量较大的情况下,就会出现因大量慢查询堆积导致DB被打挂的情况。因此,本篇文章分享一下慢查询的风险治理思路。
首先,我们需要知道什么情况下会出现慢查询。通常对于大表,未正确引用索引导致全表扫描,就会出现慢查询。慢查询出现也会经历从无到有的过程,而为何从无到有,就涉及到业务变更。以下几种业务变更场景就有可能导致慢查询的产生:
在线上环境运维过程中,我们通常需要治理慢查询的风险。慢查询会引起DB性能问题,并且当线上环境流量较大的情况下,就会出现因大量慢查询堆积导致DB被打挂的情况。因此,本篇文章分享一下慢查询的风险治理思路。
首先,我们需要知道什么情况下会出现慢查询。通常对于大表,未正确引用索引导致全表扫描,就会出现慢查询。慢查询出现也会经历从无到有的过程,而为何从无到有,就涉及到业务变更。以下几种业务变更场景就有可能导致慢查询的产生:
数据同步或者迁移操作也算是线上数据变更的一种类型。由于涉及的数据量非常大,一旦发生故障,会直接影响线上业务,并且较难止损。从变更风险管控的角度考虑,数据同步或迁移操作也需要走合理的发布窗口,并且在操作前也需要做足够的影响分析。本文就来聊一下数据同步和迁移的变更期间注意事项。
数据同步按照持续状态的不同可以分为一次性同步跟持续性同步。从质量保障的角度,要降低持续性同步的风险,需要额外考虑数据跟组件性能的监控,其它方面的考虑两者没有太大的差别。数据同步的操作手法也有很多种,既可以通过搭建中间件,实现一个导入binlog到MQ然后再导到其它存储的通路,也可以通过自建业务服务,通过批量刷数的方式主动导入大量数据。对于后者,在以前的文章当中已经提到了一些通用的风险点,但如果考虑到数据同步的需要,还会有一些额外的考量。
在接手以前的项目做开发的过程中,我们经常会遇到因为既有代码理解困难,导致代码难以删改,问题难以排查的情况。一份富含技术债的代码,不论对于当下的问题解决,还是未来的需求开发,都会形成累赘。因此,本文就分享一些通用的代码优化和治理经验。
首先我们需要从工作的角度去看待代码优化这件事情。需要捋清楚几件事情:
比起为技术而技术地去做代码重构甚至重写,锚定当前的目标,按需优化才是最好的选择。如果历史代码存在比较严重的问题,影响了核心的业务,那么必须强行去做修复,不论代码实现是否符合自己的审美。如果历史代码写的不那么美观,但线上跑的还比较稳定,那么也不建议直接做优化,更多的优先级应该放在新研发的内容上面。
精准测试在互联网领域有广泛的应用。以变更为出发点,通过对变更内容进行分析,可以确定单次变更具体涉及到哪些模块和功能点,以及是否存在夹带风险,从而从QA的视角,可以知道哪些功能模块需要做测试,以及哪些变更内容不符合预期。相比于互联网QA,游戏QA接入业务项目研发过程并没有那么深入,比如项目代码权限基本上游戏QA不会拥有,但即便如此,要在游戏测试领域应用精准测试专项技术,还是有一定思路可循。
因此,本篇文章,笔者以自身经验为出发点,讲述一下在游戏业务测试落地精准测试专项的一些思路。
近些日子想到自己尘封已久的笔记本电脑没有开机了,很多软件驱动之类的没有更新,就打算把电脑开起来做一轮批量升级。但开电脑的时候很久没有进入Win10桌面,等了很长一段时间蓝屏提示0xc0000185错误,说系统需要恢复。经历了一番折腾之后,笔者解决了这个问题。虽然不明确这个问题的根因在哪里,但还是分享一下自己收集到的一些解决方式。
首先,重装系统肯定是能解决这个问题,但不一定需要真的重装,这个成本太大了。反之,我们可以用重装系统所需要的东西,一个自带WinPE系统的U盘,把U盘插到电脑里,重启电脑,在自己电脑的BIOS里选择优先引导U盘的WinPE系统,这样下次启动电脑时候就能进去。市面上做装机服务,基本上都会用到这种系统,而这样的U盘也很好做,有一个空的U盘,然后在老毛桃之类的网站找一个一键制作的软件操作就可以。
近期在testerhome的游戏测试节点里,看到一个很有趣的帖子:针对游戏策划的配置表测试,是否有开源的框架可以用?除了问题本身之外,帖子的楼主也附了一张整个配置表测试工具的设计图,由SVN变更监控、发起检查最后到消息通知,组成了一个持续集成的配置表测试专项工程。为此,针对这个场景,笔者也希望输出一些自己对于配置表检查测试技术的一些思考。
本篇文章讲述两块内容,第一块讲下测试框架的开源,第二块讲下专项技术的设计。首先,看一下配置表测试框架开源这块的问题。
在使用Golang做后端开发的工程中,我们通常需要声明一些一些配置类或服务单例等在业务逻辑层面较为底层的实例。为了节省内存或是冷启动开销,我们通常采用lazy-load懒加载的方式去初始化这些实例。初始化单例这个行为是一个非常经典的并发处理的案例,比如在java当中,我们可能用到建立双重锁+volatile的方式保证初始化逻辑只被访问一次,并且所有线程最终都可以读取到初始化完成的实例产物。这段经典的代码可以按如下的方式编写:
在研发中,我们经常会面对到处理并发逻辑的场景,尤其是有时候在与第三方平台对接的场景下,会遇到请求限流限QPS的要求。对于限流或者限速,我们通常会用两种算法来满足需要:
这两种算法,虽然实际QPS数值可能都会有波动,但都能把速率限制在一个合理的水位。在Golang里面,这两种算法都有现成的实现可以直接用。咱们今天,就来看看这块的例子。
在后端开发当中,经常会遇到这样的场景:请求给了批量的输入,对于每一个输入,我们都要给外部发请求等待返回,然后才能继续其它自己的业务逻辑。在这样的case下,如果每一个输入串行处理的话,那么很大一部分时间都会损耗在给外部发请求这个环节,因此我们会希望把这些请求放到各个goroutine里异步执行,等待批量执行完成之后再继续后面的逻辑。这个时候,我们就可以用到这个东西:sync.WaitGroup
WaitGroup提供了增减计数以及阻塞等待计数归零的线程安全接口。当主goroutine增加计数并等待的时候,子goroutine的逻辑中若引用了一个WaitGroup实例的话,也可以在结束(defer)的时候去减少计数,这样当主goroutine自旋等待计数归零时,等待的逻辑就返回了,就继续后面的内容。整体上,就达到了等待多路并行的异步任务这一效果。
一个典型的代码案例如下:
在项目日常开发过程中,批量刷数也是有一定频率的变更场景之一,同时也是容易产生风险的一种变更操作。本文就来聊下,批量刷数的发布需要经历哪些流程,以及流程中每个环节中有什么风险点需要考虑。
首先需要了解批量刷数这个操作是个什么意义。无论是新增/删除一些数据也好,还是UPDATE某些已有线上数据也好,其背后要么对应着一个新业务开发,要么对应着一个bugfix。因此,批量刷数的本质其实就是一个业务需求,需要有完整的一套需求评审 -> 技术评审 -> 线下测试 -> 线上发布 -> 发布验证的过程。
第一个环节是需求评审。需求评审的主要的目的,一是为了做刷数的可行性评估,二是做刷数记录归档。