23 November 2015
入职两个月,经历双11的一些工作记录。

9月份入职后,主要就是在熟悉业务和流程、熟悉代码,还有就是数据加载和集群切换的工作。我们的服务有两套集群,每个集群又包含三套机房,分别是黄村、永丰和廊坊机房。集群分为线上集群和线下集群。多个集群是为了保证数据加载不影响线上用户的正常使用。三级列表页有大约1000个分类,每个分类需要加载2万个商品,如果在线上集群进行加载数据的操作,哪怕是只加载一个分类,都会引起CPU和数据库的报警。所以,线上机群只是正常展示数据,线下集群进行全量数据加载。

接口部分使用Golang语言+MySQL+JimDB+twmeproxy(JimDB可以简单的认为是Redis)开发。由我们组其他同事将异构好的商品计算好之后持久化到MySQL里面。我负责将MySQL里面的数据加载到JimDB和内存里面。Twmeproxy用来当作JimDB的前台分片代理。

10月份开始,开始着手开始更重要的双11凤凰项目开发。我们组负责的是4免1的pop商品的活动页。凤凰项目是列表页项目的一个简化项目,逻辑相似且更为简单。这对我了解项目有很大帮助。开发倒是很顺利,大概用了不到1周就开发完成了。后来就是在解决坑的踩。

坑1,丢商品。数据加载完之后,有的专题会丢商品,而且很规律。每个专题固定丢的就是这些。但是排查起来很难。我们的服务都是分布式的集群,尤其是JimDB用了twmeproxy做分片,丢的这个商品是在哪个JimDB上面丢的,我都无从判断。而且是线上有问题,而测试环境没问题。当时只能是申请了一台机器转为预发,通过给代码加日志来跟踪问题。后来终于发现在保存商品的时候出错了。之前访问JimDB的代码封装的时候,保存到JimDB的函数返回值是error错误类型,但是在实际排查的时候它从来都没有返回过错误,后来深入看代码才发现所有错误都被过滤掉了,这里影响我的排查方向。最后,看到错误输出之后,发现是没有写入JimDB的权限,再比对twmeproxy的配置,发现有一台twmeproxy的配置项填错了,填成了从JimDB,故而写入失败。总结:错误不可避免,但是错误日志很重要。如果当时的逻辑能直接看到错误日志,排查的速度能从半天时间缩减到半小时。

坑2,twmeproxy分片问题。Twmeproxy分片是根据存入键值对的键进行处理的,所以分配到每个JimDB分片上面的键是均匀的。而实际使用的过程中发现,即使键是均匀的,我们保存的值大小是不可控的。这样,有可能某一个分片分配过来的值都很大,最后导致整个分片内存满了。而JimDB对于此种情况的处理并不是LRU,而且一旦内存满了,写入就会失败。我们对应的解决方案是发现哪个分片满了,就给这个分片单独申请增加内存。

坑3,JimDB连接数问题。最后压测的时候,发现集群压测性能不是很理想。排查了很多方面,磁盘IO、MySQL读写、Redis读写等。后来发现是程序与Twmeproxy连接数过低,与压测的同事沟通改为1000之后,压测效果理想,单台机器能够支持1800的TPS。由于不同的商品被打散到了不同的服务器上面,获取这些商品虽然是通过MGet的方式获取,其实底层还是串行从每台机器上面取的数据。这里还需要优化。


原文链接:京东工作记录,转载请注明来源!

EOF