# 故事
这是一个真实事件,三年前老猫负责公司的支付资产业务。为了响应上级号召,加强国央企之间的合作,公司新谈了一个支付对接的渠道(当然这个支付渠道其实很冷门的,也是为了对接而对接,具体哪个渠道也不方便透露),由于原始支付系统的第三方支付可拓展性设计得还不错的,所以老猫对接的也是比较快的,熟悉对方的对接文档之后对着编码就好了,差不多花了三天的时间就完成联调了。一切看似很顺利地上线了。
时隔几天,收到了一个快递包裹,是一袋价值53块钱的“原皮腰果”,当时诧异,翻看了各大消费平台,都没有之前的下单记录,后来和媳妇确认了一下,她也没有下单。“难道是某个崇拜哥的小姑娘送的?不能吧”当时心里美滋滋地yy着。
不过之后的一个客诉问题,引起了老猫的重视,老猫排查下来发现一个很重大的问题,钱款的扣除和实际的订单状态对不上。说白了就是订单完结了,但是账户资产并没有完成扣除。我瞬间明白了之前那个“原皮腰果”是怎么回事儿了,当时在生产测试渠道的时候,在公司内部商城提交了订单,但是并没有付款,然而订单却成功了。
再三确认之后,确实存在这一问题。一瞬间整个人心态崩了,头皮发麻,口干舌燥,心脏“突突突”。怎么办?怎么办?生产还不知道涉及多少单子,没办法,兜不住了,先把这件事情往上抛吧(向上级领导汇报)。
具体原因是什么呢?我们来看一下对接第三方支付的大概时序流程。
# 故事
会议室里,小猫挠着头,心里暗暗叫苦着“哎,这代码都撸完了呀,改起来成本也太大了。”
原来就在刚才,组长找到了小猫,说代码review过程中发现有些数据表模型设计得不合理,要求小猫改掉。小猫大概是设计了一个配置表,为了省事儿,小猫直接把相关的配置设计成了text类型的存储形式。
关于这种业务场景下使用text文本类型存储,组长指出了以下缺点:
- 在内存中处理Text字段时,由于需要处理大量数据,可能会导致内存使用过度,影响数据库性能。
- Text字段无法创建索引,这会导致数据库在执行查询时无法利用索引来加速搜索。虽然可以通过全文索引来改善搜索性能,但是却会有诸多限制,例如只能用于InnoDB引擎,并且索引只能建立在不超过1000字节的前缀上。
- 目前刚设计的时候就用text类型,后期随着数据量的增长以及业务需求的变化,可能就意味着要将text类型继续扩大变成,LongText或MediumText类型,这样的转换既费时又可能需要额外的存储空间。
“组长说的也有道理,但是为什么现在才指出来,当时方案模型评审的时候咋提呢,哎,醉了醉了,现在业务逻辑都按照现有方案开发完了,才提出来.....”
“改?要重写逻辑,不改?万一今后真的出现上面组长说的这些问题,不得被喷死......”
彷徨过后,小猫终于下定了决心,改了吧,长痛不如短痛...反正如果不改的话,受罪的还是自己。于是加班是少不了了......
# 故事
地铁上,小帅双目空洞地望着窗外...绝望,发自内心地感到绝望...
距离失业已经过去两个月了,这是小帅接到的第四次面试邀请。“回去等通知吧...”,简简单单的六个字,把小帅的心再次打入了冰窖。
上次“【ThreadLocal问出花
“Java中的锁了解吧?介绍一下吧”,面试官不紧不慢地问到。
大家好,我是老猫。
大概在月初的时候,我发了一篇文章【当程序员之后?(真心话)
老猫觉得当时的回答太过敷衍了,甚至有点不太负责,所以在此也要向这位小伙伴道个歉。后来老猫仔细结合日常工作中的思考方式,把想到的又重新梳理总结了一下。分享给各位,希望对大家有所帮助。
# 背景
小猫维护现有的系统也有一段时间了,踩坑也不少,事故不少。感兴趣的小伙伴可以了解一下,往期的小猫踩坑记合集
这天,小猫找到了商城系统的第一任开发老A开始聊天。
“你们这系统是真坑,我都吃过好多次亏了,太烂了...”小猫开玩笑地吐槽道。
“我们当时其实还是花了很长的一段时间去做设计以及评审的,每一步都是有严格把控的,当时系统总体骨架还是相当清晰的,也没有那么多新的概念,你说现在系统不行了,可不能怪我们啊。一会我给你原始设计文档看看。后面经过了很多研发的手了,甚至运营和产品都换了好几拨了,每任运营可能对当前系统的要求都不一样吧,大家理解可能都不同......”老A侃侃而言着。
小猫抿了口刚倒的茶,意味深长地看着老A...
# 故事
春天,办公室外的世界总是让人神往的,小猫带着耳机,托着腮帮,望着外面美好的春光神游着...
一声不和谐的座机电话声打破这份本该属于小猫的宁静,“hi,小猫,线上有个客户想购买A产品规格的商品,投诉说下单总是失败,帮忙看一下啥原因。”客服部小姐姐甜美的声音从电话那头传来。“哦哦,好,我看一下,把商品编号发一下吧......”
由于前一段时间的系统熟悉,小猫对现在的数据表模型已经了然于胸,当下就直接定位到了商品规格信息表,发现数据库中客户想购买的规格已经被下架了,但是前端的缓存好像并没有被刷新。
小猫在系统中找到了之前开发人员留的后门接口,直接curl语句重新刷新了一下接口,缓存问题搞定了。
关于商品缓存和数据库不一致的情况,其实小猫一周会遇到好几个这样的客诉,他深受DB以及缓存不一致的苦,于是他下定决心想要从根本上解决问题,而不是curl调用后门接口......
地铁上刷到一个话题,觉得挺有意思的,如下。
看到很多朋友在下面吐槽,有说加班是真的多,有说找对象是真的难,有说程序员爱穿格子衫是假爱背电脑是真的等等,大家吐槽得都挺欢乐的。老猫也开始复盘这些年的经历,更多想聊的可能还是一个后端程序员的真实感悟。
分享是最有效的学习方式。
博客:https://blog.ktdaddy.com/
# 故事
新年新气象,小猫也是踏上了新年新征程,自从小猫按照老猫给的建议【系统梳理大法
类似于开放平台的老六接到客户的需求,需要在查询订单新增一个下单时间的返回值,然后这就需要提供底层服务的小猫在接口层给出这个字段,然后老六通过包装之后给客户。由于需求比较简单,所以加完字段之后,老六和小猫也就直接上线了。
上线之后事儿来了,对面客户研发一直询问为什么还是没有下单时间,总是空的。老六于是直接找到了小猫,可是小猫经过了一些列的自测发现返回值都是有的,后来排查到在老六封装之后值不见了。经过仔细排查,终于找到了问题,虽然没有造成太大的影响,但是总归给客户研发的心里留下了一个不好的印象。
虽然下单时间老六和小猫定义的都是orderTime这样一个字段,但是字段类型小猫用的是Date类型而老六用的是LocalDate,恰巧老六在进行对象赋值的时候偷了个懒直接用了spring的BeanUtils.copyProperties工具类,于是导致日期类型的值并没有被赋值过去,踩坑了。
老六这才回想起前段时间架构师在群里@ALL的一段话,“大家用BeanUtils拷贝对象的时候注意点,有坑啊,大家尽量用get,set方法啊”。当时的老六不以为意,想着,“切,这得多麻烦,一个个set不花时间啊,有工具类不用”。现在想来看来是真踩到BeanUtils的坑了。
老六一边改着代码一边叨叨:“这也没说坑在哪里啊......”