这16个好习惯,可以减少80%非业务的bug!(下)
9.获取对象的属性,先判断对象是否为空这个点本来也属于「采取措施规避运行时异常」的,但是我还是把它拿出来,当做一个重点来写,因为平时空指针异常太常见了,一个手抖不注意,就导致空指针报到生产环境去了。
所以,你要获取对象的属性时,尽量不要相信「理论上不为空」,我们顺手养成习惯判断一下是否为空,再获取对象的属性。正例:
if(object!=null){
String name = object.getName();
}
10.多线程异步优先考虑恰当的线程池,而不是new thread,同时考虑线程池是否隔离
为什么优先使用线程池?使用线程池有这几点好处呀!
· 它帮我们管理线程,避免增加创建线程和销毁线程的资源损耗。
· 提高响应速度。
· 重复利用。
同时呢,尽量不要所有业务都共用一个线程池,需要考虑「线程池隔离」。就是不同的关键业务,分配不同的线程池,然后线程池参数也要考虑恰当哈。
11. 手动写完代码业务的SQL,先拿去数据库跑一下,同时也explain看下执行计划。
手动写完业务代码的SQL,可以先把它拿到数据库跑一下,看看有没有语法错误嘛。有些小伙伴不好的习惯就是,写完就把代码打包上去测试服务器,其实把SQL放到数据库执行一下,可以规避很多错误的。
同时呢,也用「explain看下你Sql的执行计划」,尤其走不走索引这一块。
explain select * from user where userid =10086 or age =18;
12.调用第三方接口,需要考虑异常处理,安全性,超时重试这几个点。
调用第三方服务,或者分布式远程服务的的话,需要考虑。
· 异常处理(比如,你调别人的接口,如果异常了,怎么处理,是重试还是当做失败)。
· 超时(没法预估对方接口一般多久返回,一般设置个超时断开时间,以保护你的接口)。
· 重试次数(你的接口调失败,需不需要重试,需要站在业务上角度思考这个问题。
简单一个例子,你一个http请求别人的服务,需要考虑设置connect-time,和retry次数。
如果是转账等重要的第三方服务,还需要考虑「签名验签」,「加密」等。
13.接口需要考虑幂等性
接口是需要考虑幂等性的,尤其抢红包、转账这些重要接口。最直观的业务场景,就是「用户连着点击两次」,你的接口有没有hold住。
· 幂等(idempotent、idempotence)是一个数学与计算机学概念,常见于抽象代数中。
· 在编程中.一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。幂等函数,或幂等方法,是指可以使用相同参数重复执行,并能获得相同结果的函数。
一般「幂等技术方案」有这几种:
· 查询操作
· 唯一索引
· token机制,防止重复提交
· 数据库的delete删除操作
· 乐观锁
· 悲观锁
· Redis、zookeeper 分布式锁(以前抢红包需求,用了Redis分布式锁)
· 状态机幂等
14. 多线程情况下,考虑线性安全问题
在「高并发」情况下,HashMap可能会出现死循环。因为它是非线性安全的,可以考虑使用ConcurrentHashMap。所以这个也尽量养成习惯,不要上来反手就是一个new HashMap();
Hashmap、Arraylist、LinkedList、TreeMap等都是线性不安全的;
Vector、Hashtable、ConcurrentHashMap等都是线性安全的;
15.主从延迟问题考虑
先插入,接着就去查询,这类代码逻辑比较常见,这「可能」会有问题的。一般数据库都是有主库,从库的。写入的话是写主库,读一般是读从库。如果发生主从延迟,很可能出现你插入成功了,但是却查询不到的情况。
· 如果是重要业务,需要考虑是否强制读主库,还是再修改设计方案。
· 但是呢,有些业务场景是可以接受主从稍微延迟一点的,但是这个习惯还是要有吧。
· 写完操作数据库的代码,想下是否存在主从延迟问题。
16.使用缓存的时候,考虑缓存跟DB的一致性,还有(缓存穿透、缓存雪崩和缓存击穿)
通俗点说,我们使用缓存就是为了「查得快,接口耗时小」。但是呢,用到缓存,就需要「注意缓存与数据库的一致性」问题。同时,还需要规避缓存穿透、缓存雪崩和缓存击穿三大问题。
缓存雪崩:指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。
缓存穿透:指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,进而给数据库带来压力。
缓存击穿:指热点key在某个时间点过期的时候,而恰好在这个时间点对这个Key有大量的并发请求过来,从而大量的请求打到db。
页:
[1]