一次线上OOM排查和处理

项目场景:

前段时间项目组出现了OOM现象,导致机器重启,部分业务受到影响,这里做一个复盘和总结


问题描述:

原因:由于pda这种扫码枪,扫到一个空的商品条码,而在前端和或者后端接口层都没有做这种为空校验,而查询数据库时用的是“OR”导致没有走索引,而对于商品信息全表扫描,那个商品表的数据量大约为2000w。而那个表是个宽表,大约有100个字段,这些数据加载到内存,达到内存设置的告警线,而导致机器重启。
APP 中接收数据代码:

func (o Object) ScanCode(ctx context.Context, code string) ([]*SKUList, *wmserror.WMSError) {
	
	var skuList []*SKUList
	
	db := getSKUDBInstance(ctx)
	db = db.Where("sku_code = ? or upc_code1 = ? or upc_code2 = ? or partner_sku_code = ? or supplier_code = ?", code, code, code, code, code)
	err := db.Find(&skuList).GetError()
	if err != nil {
		return nil, wmserror.NewError(constant.ErrDB, err.Error())
	}
	return skuList, nil
}

原因分析:

这里当扫到的商品码为空的情况下不会走到索引,会导致全表扫描,这表数据量太大,当这些数据全部加载到内存中后,数据撑爆了内存


解决方案:

底层每个调用数据库层做强校验,把这种空的数据直接不让其去占用网络链接,不去请求数据库。就可以解决。

func (o Object) ScanCode(ctx context.Context, code string) ([]*SKUList, *wmserror.WMSError) {

	var skuList []*SKUList
	if len(code) == 0 {
		return skuList, nil
	}
	
	db := getSKUDBInstance(ctx)
	db = db.Where("sku_code = ? or upc_code1 = ? or upc_code2 = ? or partner_sku_code = ? or supplier_code = ?", code, code, code, code, code)
	err := db.Find(&skuList).GetError()
	if err != nil {
		return nil, wmserror.NewError(constant.ErrDB, err.Error())
	}
	return skuList, nil
}

思考:

在开发时我们要做防御性编程,如果你写的业务逻辑受到数据的影响很大,那么接口层一定要做强校验,这样才可以保证不会让数据继续流转下去,一定需要做强校验,带着怀疑的态度去编码,而不是相信别人的接口的态度去编码。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值