Part 1 – 易错点

--  edit by liudeyu,If you have any adivice or suggestion, please participate in the discussion

命名规范方面:

1. 【强制】 POJO 类中的任何布尔类型的变量, 都不要加 is 前缀,否则部分框架解析会引起序列化错误。
说明: 在本文 MySQL 规约中的建表约定第一条,表达是与否的值采用 is_xxx 的命名方式,所以,需要在
<resultMap>设置从 is_xxx 到 xxx 的映射关系。
反例: 定义为基本数据类型 Boolean isDeleted 的属性,它的方法也是 isDeleted(),框架在反向解析的时
候, “误以为” 对应的属性名称是 deleted,导致属性获取不到,进而抛出异常。

2.【强制】 杜绝完全不规范的缩写, 避免望文不知义。
反例: AbstractClass“缩写” 命名成 AbsClass; condition“缩写” 命名成 condi,此类随意缩写严重降低了代码的可阅读性。

3.【推荐】 为了达到代码自解释的目标,任何自定义编程元素在命名时,使用尽量完整的单词组合来表达。

!!! java 变量为什么长,就是因为这个原因,虽然长,但是如果能望文生义,也是大有裨益。

正例:在 JDK 中,对某个对象引用的 volatile 字段进行原子更新的类名为:AtomicReferenceFieldUpdater。
反例: 常见的方法内变量为 int a;的定义方式。

4.【推荐】 如果模块、 接口、类、方法使用了设计模式,在命名时需体现出具体模式。  
说明: 将设计模式体现在名字中,有利于阅读者快速理解架构设计理念。
正例: public class OrderFactory;
public class LoginProxy;
public class ResourceObserver

5. 【强制】 不要使用一个常量类维护所有常量, 要按常量功能进行归类,分开维护。

!! 这个强制一下,常量用显而易见的命名来命名类,查找时候,容易定位

说明: 大而全的常量类, 杂乱无章, 使用查找功能才能定位到修改的常量,不利于理解,也不利于维护。
正例: 缓存相关常量放在类 CacheConsts 下;系统配置相关常量放在类 ConfigConsts 下。

代码方面:

6.【强制】 外部正在调用或者二方库依赖的接口,不允许修改方法签名,避免对接口调用方产生影响。接口过时必须加@Deprecated 注解,并清晰地说明采用的新接口或者新服务是什么。

!! 开放封闭原则,不管怎样对外暴露的api, public接口,要保证兼容性,不准随便删减接口(加可以),你删减一个前面版本有的接口,或者变动

之前版本有的接口,你让引用你的库的外部代码,要改多少,要有良心,不随便改已有接口,不推荐使用的,直接加@Deprecated

作为 库 或是sdk开发者,更应该如此,你改几次旧接口,每次升级版本,使用者需要改动调用处的话,不能无缝升级的话,大家肯定是怨声载道,对你这个库充满抱怨。不得已时候,进行周知。

7. 【强制】Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。
正例: "test".equals(object);
反例: object.equals("test");
说明: 推荐使用 java.util.Objects#equals( JDK7 引入的工具类) 。

8. 【强制】 所有整型包装类对象之间值的比较, 全部使用 equals 方法比较。
说明: 对于 Integer var = ? 在-128 至 127 之间的赋值, Integer 对象是在 IntegerCache.cache 产生,会复用已有对象,这个区间内的 Integer 值可以直接使用==进行判断,但是这个区间之外的所有数据,

都会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用 equals 方法进行判断。

!! 代码中已经有了这种写法了,要规避,不直接 ==

9.【强制】 禁止使用构造方法 BigDecimal(double)的方式把 double 值转化为 BigDecimal 对象。
说明: BigDecimal(double)存在精度损失风险,在精确计算或值比较的场景中可能会导致业务逻辑异常。

如: BigDecimal g = new BigDecimal(0.1f); 实际的存储值为: 0.10000000149

正例: 优先推荐入参为 String 的构造方法,或使用 BigDecimal 的 valueOf 方法,此方法内部其实执行了
Double 的 toString,而 Double 的 toString 按 double 的实际能表达的精度对尾数进行了截断。
BigDecimal recommend1 = new BigDecimal("0.1");
BigDecimal recommend2 = BigDecimal.valueOf(0.1);

10. 关于基本数据类型与包装数据类型的使用标准如下: 

1) 【强制】 所有的 POJO 类属性必须使用包装数据类型。
2) 【强制】 RPC 方法的返回值和参数必须使用包装数据类型。
3) 【推荐】 所有的局部变量使用基本数据类型。

说明: POJO 类属性没有初值是提醒使用者在需要使用时,必须自己显式地进行赋值,任何 NPE 问题,或者入库检查,都由使用者来保证。
正例: 数据库的查询结果可能是 null,因为自动拆箱,用基本数据类型接收有 NPE 风险。

反例: 某业务的交易报表上显示成交总额涨跌情况,即正负 x%, x 为基本数据类型,调用的 RPC 服务,调
用不成功时,返回的是默认值,页面显示为 0%,这是不合理的,应该显示成中划线-。所以包装数据类型
的 null 值,能够表示额外的信息,如:远程调用失败,异常退出

!! 这个注意,用包装类型,可以避免一些,接受参数或者是查库的NPE风险,强制要求, 主要表现在对外传输的变量值 都用包装类型

13.【强制】 定义 DO/DTO/VO 等 POJO 类时,不要设定任何属性默认值。

反例: POJO 类的 createTime 默认值为 new Date(), 但是这个属性在数据提取时并没有置入具体值,在
更新其它字段时又附带更新了此字段,导致创建时间被修改成当前时间

14.【强制】 构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在 init 方法中。

15. 【强制】 关于 hashCode 和 equals 的处理,遵循如下规则:

1) 只要重写 equals,就必须重写 hashCode。
2) 因为 Set 存储的是不重复的对象,依据 hashCode 和 equals 进行判断,所以 Set 存储的对象必须重写
这两个方法。
3) 如果自定义对象作为 Map 的键,那么必须覆写 hashCode 和 equals。

说明: String 因为重写了 hashCode 和 equals 方法,所以我们可以愉快地使用 String 对象作为 key 来使
用。

16. 【强制】 在使用 java.util.stream.Collectors 类的 toMap()方法转为 Map 集合时,一定要使用含有参数类型为 BinaryOperator, 参数名为 mergeFunction 的方法

否则当出现相同 key值时会抛出 IllegalStateException 异常。

!! 容易忽略,注意

17. 【强制】 在使用 java.util.stream.Collectors 类的 toMap()方法转为 Map 集合时,一定要注意当 value 为 null 时会抛 NPE 异常。

说明: 在 java.util.HashMap 的 merge 方法里会进行如下的判断:

if (value == null || remappingFunction == null)
       throw new NullPointerException();

反例:
List<Pair<String, Double>> pairArrayList = new ArrayList<>(2);
pairArrayList.add(new Pair<>("version1", 4.22));
pairArrayList.add(new Pair<>("version2", null));
Map<String, Double> map = pairArrayList.stream().collect(
// 抛出 NullPointerException 异常
Collectors.toMap(Pair::getKey, Pair::getValue, (v1, v2) -> v2));

解决: stream 中 使用 filter 过滤一下 为null 的entry

18. 【强制】 ArrayList 的 subList 结果不可强转成 ArrayList

否则会抛出 ClassCastException 异常: java.util.RandomAccessSubList cannot be cast to java.util.ArrayList。
说明: subList 返回的是 ArrayList 的内部类 SubList, 并不是 ArrayList 而是 ArrayList 的一个视图,对
于 SubList 子列表的所有操作最终会反映到原列表上。

解决: 定义变量, 操作对象的时候,也是提倡用接口来操纵,能不具现化到子类就不具现化到子类,集合对象,基本都可用 定义的接口来操纵,接口中的

方法一般已足够使用,面向接口编程。

19. 【强制】 注意不可变容器,不要进行 增删操纵,常见场景可以从接口命名中发现

例子:

  1. 使用 Map 的方法 keySet()/values()/entrySet()返回集合对象时,不可以对其进行添
    加元素操作,否则会抛出 UnsupportedOperationException 异常。

2.  Collections 类返回的对象,如: emptyList()/singletonList()等都是 immutable list,
不可对其进行添加或者删除元素的操作。

3.  subList 场景中, 高度注意对父集合元素的增加或删除, 均会导致子列表的遍历、
增加、删除产生 ConcurrentModificationException 异常。

4.  使用工具类 Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方法,
它的 add/remove/clear 方法会抛出 UnsupportedOperationException 异常。

解释: 这些接口,都有让人遍历查看元素的意图,并不是用来让你操纵元素的。类似的还有,迭代元素过程中,不要进行,增删操纵,会抛同步修改异常。

这样的写法也不规范。

20【强制】 不要在 foreach 循环里进行元素的 remove/add 操作。 remove 元素请使用 Iterator
方式,如果并发操作,需要对 Iterator 对象加锁。
正例:
List<String> list = new ArrayList<>();
list.add("1");
list.add("2");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
if (删除元素的条件) {
        iterator.remove();

}

}

反例:
for (String item : list) {
if ("1".equals(item)) {
    list.remove(item);
    }
}

!!  注意,不要在for 迭代中,进行增删操作

21.【推荐】 使用 entrySet 遍历 Map 类集合 KV,而不是 keySet 方式进行遍历。

说明: keySet 其实是遍历了 2 次,一次是转为 Iterator 对象,另一次是从 hashMap 中取出 key 所对应的value。

而 entrySet 只是遍历了一次就把 key 和 value 都放到了 entry 中,效率更高。如果是 JDK8,使用Map.forEach 方法。
正例: values()返回的是 V 值集合,是一个 list 集合对象; keySet()返回的是 K 值集合,是一个 Set 集合对
象; entrySet()返回的是 K-V 值组合集合。

解释: 容易无意识,写出用keySet迭代,效率没那么高,推荐用 entry 迭代

22. 【强制】 创建线程或线程池时请指定有意义的线程名称,方便出错时回溯。

23. 【强制】 必须回收自定义的 ThreadLocal 变量,尤其在线程池场景下,线程经常会被复用
如果不清理自定义的 ThreadLocal 变量,可能会影响后续业务逻辑和造成内存泄露等问题。

尽量在代理中使用 try-finally 块进行回收。

正例:
objectThreadLocal.set(userInfo);
try {
      // ...
} finally {
      objectThreadLocal.remove();
}

24. 【强制】 高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁; 能锁区块,就不要锁整个方法体; 能用对象锁,就不要用类锁。
说明: 尽可能使加锁的代码块工作量尽可能的小,避免在锁代码块中调用 RPC 方法。

关于,java中的无锁容器,在juc包中有很多体现,可以了解下。包括常见的 List,Set,Map接口,包括原子变量 AtomicReference,AtomicInteger 等等都有涉及,

有对应需求的时候,不妨可以先看下有没有对应的高效容器实现。

25.【强制】 对多个资源、数据库表、对象同时加锁时,需要保持一致的加锁顺序,否则可能会造成死锁。

说明: 线程一需要对表 A、 B、 C 依次全部加锁后才可以进行更新操作,那么线程二的加锁顺序也必须是 A、
B、 C,否则可能出现死锁

26.【强制】 并发修改同一记录时,避免更新丢失, 需要加锁。 要么在应用层加锁,要么在缓存加
锁,要么在数据库层使用乐观锁,使用 version 作为更新依据。

说明: 如果每次访问冲突概率小于 20%,推荐使用乐观锁,否则使用悲观锁。乐观锁的重试次数不得小于
3 次。

27.【强制】 多线程并行处理定时任务时, Timer 运行多个 TimeTask 时,只要其中之一没有捕获抛
出的异常,其它任务便会自动终止运行, 使用 ScheduledExecutorService 则没有这个问题。

使用:ScheduledExecutorService

28.【推荐】 资金相关的金融敏感信息,使用悲观锁策略。
说明: 乐观锁在获得锁的同时已经完成了更新操作,校验逻辑容易出现漏洞,另外,乐观锁对冲突的解决策略有较复杂的要求,

处理不当容易造成系统压力或数据异常,所以资金相关的金融敏感信息不建议使用乐观锁更新。
正例: 悲观锁遵循一锁二判三更新四释放的原则

解释: 在资金要求数据一定要正确的场景, 放弃性能保证正确性,孰轻孰重要懂判断

数据库相关:

数据库和建表相关,统一强制的规范是必要的。这个比起前面的编程规范,更不能妥协。因为建表后,有数据以后,修改表结构就是很麻烦的事情。

29. 【强制】 表达是与否概念的字段,必须使用 is_xxx 的方式命名,数据类型是 unsigned tinyint( 1 表示是, 0 表示否)。
说明: 任何字段如果为非负数,必须是 unsigned。
注意: POJO 类中的任何布尔类型的变量,都不要加 is 前缀,所以,需要在<resultMap>设置从 is_xxx 到
Xxx 的映射关系。数据库表示是与否的值,使用 tinyint 类型,坚持 is_xxx 的命名方式是为了明确其取值含
义与取值范围。
正例: 表达逻辑删除的字段名 is_deleted, 1 表示删除, 0 表示未删除。

30. 【强制】 表名、字段名必须使用小写字母或数字, 禁止出现数字开头,禁止两个下划线中间只出现数字。

数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。

说明: MySQL 在 Windows 下不区分大小写,但在 Linux 下默认是区分大小写。因此,数据库名、表名、
字段名,都不允许出现任何大写字母,避免节外生枝。
正例: aliyun_admin, rdc_config, level3_name
反例: AliyunAdmin, rdcConfig, level_3_name

31. 【强制】 禁用保留字,如 desc、 range、 match、 delayed 等, 请参考 MySQL 官方保留字。

解释: 有些关键字,没注意就冲突了,例如: desc,describe

32. 【强制】 主键索引名为 pk_字段名;唯一索引名为 uk_字段名; 普通索引名则为 idx_字段名。
说明: pk_ 即 primary key; uk_ 即 unique key; idx_ 即 index 的简称

33. 【强制】 小数类型为 decimal,禁止使用 float 和 double。
说明: 在存储的时候, float 和 double 都存在精度损失的问题,很可能在比较值的时候,得到不正确的
结果。如果存储的数据范围超过 decimal 的范围,建议将数据拆成整数和小数并分开存储。

34. 【强制】 表必备三字段: id, gmt_create, gmt_modified。
说明: 其中 id 必为主键,类型为 bigint unsigned、单表时自增、步长为 1。 gmt_create, gmt_modified的类型均为 datetime 类型,

前者现在时表示主动式创建,后者过去分词表示被动式更新。

解释: 命名可改,三字段要有,更新数据表记录时,必须同时更新记录对应的 gmt_modified 字段值为当前时间。

35.【推荐】 表的命名最好是遵循“业务名称_表的作用” 。
正例: alipay_task / force_project / trade_config

36.【推荐】 字段允许适当冗余,以提高查询性能,但必须考虑数据一致。冗余字段应遵循:
1) 不是频繁修改的字段。
2) 不是唯一索引的字段。
3) 不是 varchar 超长字段,更不能是 text 字段。
正例: 各业务线经常冗余存储商品名称,避免查询时需要调用 IC 服务获取。

37.【参考】 合适的字符存储长度,不但节约数据库表空间、节约索引存储,更重要的是提升检索
速度。
正例: 无符号值可以避免误存负数, 且扩大了表示范围。

38. 【强制】 业务上具有唯一特性的字段,即使是组合字段,也必须建成唯一索引。

39. 【强制】 超过三个表禁止 join。需要 join 的字段,数据类型保持绝对一致; 多表关联查询时,
保证被关联的字段需要有索引。
说明: 即使双表 join 也要注意表索引、 SQL 性能。

40. 【强制】 在 varchar 字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据
实际文本区分度决定索引长度。

说明: 索引的长度与区分度是一对矛盾体,一般对字符串类型数据,长度为 20 的索引,区分度会高达 90%
以上,可以使用 count(distinct left(列名, 索引长度))/count(*)的区分度来确定。

使用前缀索引,varchar 长度比较长的时候

41. 【推荐】 如果有 order by 的场景,请注意利用索引的有序性。 order by 最后的字段是组合索引的一部分,

并且放在索引组合顺序的最后,避免出现 file_sort 的情况,影响查询性能。

正例: where a=? and b=? order by c; 索引: a_b_c
反例: 索引如果存在范围查询, 那么索引有序性无法利用,如: WHERE a>10 ORDER BY b; 索引 a_b 无法排序。

42. 【推荐】 利用覆盖索引来进行查询操作, 避免回表。

说明: 如果一本书需要知道第 11 章是什么标题,会翻开第 11 章对应的那一页吗?目录浏览一下就好,这
个目录就是起到覆盖索引的作用。

正例: 能够建立索引的种类分为主键索引、唯一索引、普通索引三种,而覆盖索引只是一种查询的一种效
果,用 explain 的结果, extra 列会出现: using index。

43. 【推荐】 利用延迟关联或者子查询优化超多分页场景。

说明: MySQL 并不是跳过 offset 行,而是取 offset+N 行,然后返回放弃前 offset 行,返回 N 行,那当
offset 特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过特定阈值的页数进行 SQL改写。
正例: 先快速定位需要获取的 id 段,然后再关联:
SELECT a.* FROM 表 1 a, (select id from 表 1 where 条件 LIMIT 100000,20 ) b where a.id=b.id

44. 【强制】 使用 ISNULL()来判断是否为 NULL 值。

说明: NULL 与任何值的直接比较都为 NULL。
1) NULL<>NULL 的返回结果是 NULL, 而不是 false。
2) NULL=NULL 的返回结果是 NULL, 而不是 true。
3) NULL<>1 的返回结果是 NULL,而不是 true。
反例: 在 SQL 语句中,如果在 null 前换行,影响可读性。 select * from table where column1 is null and
column3 is not null; 而`ISNULL(column)`是一个整体,简洁易懂。从性能数据上分析, `ISNULL(column)`
执行效率更快一些

45. 【强制】 不得使用外键与级联,一切外键概念必须在应用层解决。
说明: (概念解释) 学生表中的 student_id 是主键,那么成绩表中的 student_id 则为外键。如果更新学
生表中的 student_id,同时触发成绩表中的 student_id 更新, 即为级联更新。外键与级联更新适用于单机
低并发,不适合分布式、高并发集群;级联更新是强阻塞,存在数据库更新风暴的风险;外键影响数据库
的插入速度。

46. 【强制】 禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。

47. 【强制】 数据订正(特别是删除或修改记录操作) 时,要先 select,避免出现误删除,确认无
误才能执行更新语句。

48. 【强制】 对于数据库中表记录的查询和变更,只要涉及多个表,都需要在列名前加表的别名(或表名)进行限定。
说明: 对多表进行查询记录、更新记录、删除记录时,如果对操作列没有限定表的别名(或表名),并且操作列在多个表中存在时,就会抛异常。
正例: select t1.name from table_first as t1 , table_second as t2 where t1.id=t2.id;
反例: 在某业务中,由于多表关联查询语句没有加表的别名(或表名)的限制,正常运行两年后,最近在
某个表中增加一个同名字段,在预发布环境做数据库变更后,线上查询语句出现出 1052 异常: Column
'name' in field list is ambiguous。

49. 【推荐】 不要写一个大而全的数据更新接口。

反例: 传入为 POJO 类,不管是不是自己的目标更新字段,都进行 update table set c1=value1,c2=value2,c3=value3; 这是不对的。

执行 SQL 时,不要更新无改动的字段,一是易出错;二是效率低;三是增加 binlog 存储。

50. 【推荐】 @Transactional 事务不要滥用。事务会影响数据库的 QPS,另外使用事务的地方需要考虑各方面的回滚方案,

包括缓存回滚、搜索引擎回滚、消息补偿、统计修正等

服务器相关:

51. 【强制】 调大服务器所支持的最大文件句柄数( File Descriptor,简写为 fd) 。

说明: 主流操作系统的设计是将 TCP/UDP 连接采用与文件一样的方式去管理,即一个连接对应于一个 fd。
主流的linux服务器默认所支持最大fd数量为1024,当并发连接数很大时很容易因为 fd不足而出现“open Java too many files” 错误,导致新的连接无法建立。

建议将 linux 服务器所支持的最大句柄数调高数倍(与服务器的内存数量相关)。

52. 【强制】给 JVM 环境参数设置-XX:+HeapDumpOnOutOfMemoryError 参数,让 JVM 碰到 OOM场景时输出 dump 信息。

说明: OOM 的发生是有概率的,甚至相隔数月才出现一例,出错时的堆内信息对解决问题非常有帮助。

53. 【推荐】 在线上生产环境, JVM 的 Xms 和 Xmx 设置一样大小的内存容量, 避免在 GC 后调整堆大小带来的压力。

解释: xms 初始化堆大小, xmx 最大堆大小,至于其他jvm 参数,包括新生代老年代比例, meta spece大小,

需要根据特定场景特定分析, 和是否要new 对象的速率,和希望 minor gc 和 full gc 频率来判断。

异常和日志处理:

54.【强制】 Java 类库中定义的可以通过预检查方式规避的 RuntimeException 异常不应该通过catch 的方式来处理,比如: NullPointerException, IndexOutOfBoundsException 等等。
说明: 无法通过预检查的异常除外,比如,在解析字符串形式的数字时, 可能存在数字格式错误, 不得不
通过 catch NumberFormatException 来实现。
正例: if (obj != null) {...}
反例: try { obj.method(); } catch (NullPointerException e) {…}

55. 【强制】 catch 时请分清稳定代码和非稳定代码,稳定代码指的是无论如何不会出错的代码。对于非稳定代码的 catch 尽可能进行区分异常类型,再做对应的异常处理。
说明: 对大段代码进行 try-catch,使程序无法根据不同的异常做出正确的应激反应,也不利于定位问题,这是一种不负责任的表现。
正例: 用户注册的场景中,如果用户输入非法字符, 或用户名称已存在, 或用户输入密码过于简单,在程序上作出分门别类的判断,并提示给用户。

56. 【强制】 在调用 RPC、二方包、或动态生成类的相关方法时,捕捉异常必须使用 Throwable类来进行拦截。

说明: 通过反射机制来调用方法,如果找不到方法,抛出 NoSuchMethodException。什么情况会抛出NoSuchMethodError 呢?

二方包在类冲突时,仲裁机制可能导致引入非预期的版本使类的方法签名不匹配,或者在字节码修改框架(比如: ASM)动态创建或修改类时,

修改了相应的方法签名。这些情况,即使代码编译期是正确的,但在代码运行期时,会抛出 NoSuchMethodError。

57.【推荐】 防止 NPE,是程序员的基本修养,注意 NPE 产生的场景:
1) 返回类型为基本数据类型, return 包装数据类型的对象时,自动拆箱有可能产生 NPE。
反例: public int f() { return Integer 对象}, 如果为 null,自动解箱抛 NPE。
2) 数据库的查询结果可能为 null。
3) 集合里的元素即使 isNotEmpty,取出的数据元素也可能为 null。
4) 远程调用返回对象时,一律要求进行空指针判断,防止 NPE。
5) 对于 Session 中获取的数据,建议进行 NPE 检查,避免空指针。
6) 级联调用 obj.getA().getB().getC();一连串调用,易产生 NPE。
正例: 使用 JDK8 的 Optional 类来防止 NPE 问题。

58.【推荐】 方法的返回值可以为 null,不强制返回空集合,或者空对象等,必须添加注释充分说明什么情况下会返回 null 值。
说明: 本手册明确防止 NPE 是调用者的责任。即使被调用方法返回空集合或者空对象,对调用者来说,也并非高枕无忧,必须考虑到远程调用失败、 序列化失败、运行时异常等场景返回 null 的情况

解释:但是 返回集合,没有数据时候,返回为空集合,会给调用者以便利,像常见orm框架,查询list 数据,如果没有数据会返回空数据list,给调用者以便利

59.【强制】 所有日志文件至少保存 15 天,因为有些异常具备以“周” 为频次发生的特点。 对于当天日志,以“应用名.log” 来保存

保存在/home/admin/应用名/logs/</font>目录下,过往日志格式为: {logname}.log.{保存日期},日期格式: yyyy-MM-dd
说明: 以 mppserver 应用为例,日志保存在/home/admin/mppserver/logs/mppserver.log,历史日志
名称为 mppserver.log.2016-08-01

60.【强制】 应用中的扩展日志( 如打点、临时监控、访问日志等) 命名方式:appName_logType_logName.log。

logType:日志类型, 如 stats/monitor/access 等; logName:日志描述,这种命名的好处:通过文件名就可知道日志文件属于什么应用,什么类型,什么目的,也有利于归类查找。
说明: 推荐对日志进行分类, 如将错误日志和业务日志分开存放,便于开发人员查看,也便于通过日志对系统进行及时监控。
正例: mppserver 应用中单独监控时区转换异常,如: mppserver_monitor_timeZoneConvert.log

数据库加强版:

表设计:

61.【建议】表中所有字段必须都是NOT NULL属性,业务可以根据需要定义DEFAULT值。因为使用NULL值会存在每一行都会占用额外存储空间、数据迁移容易出错、聚合函数计算结果偏差等问题。

62.【建议】建议对表里的blob、text等大字段,垂直拆分到其他表里,仅在需要读这些对象的时候才去select。

63.【建议】反范式设计:把经常需要join查询的字段,在其他表里冗余一份。如user_name属性在user_account,user_login_log等表里冗余一份,减少join查询。还要不经常变动,变动时候,冗余字段也需要维护,会比较麻烦一点。

64.【强制】中间表用于保留中间结果集,名称必须以tmp_开头。备份表用于备份或抓取源表快照,名称必须以bak_开头。中间表和备份表定期清理。

65.【强制】对于超过100W行的大表进行alter table,必须经过DBA审核,并在业务低峰期执行。因为alter table会产生表锁,期间阻塞对于该表的所有写入,对于业务可能会产生极大影响。

66.【建议】表中的自增列(auto_increment属性),推荐使用bigint类型。因为无符号int存储范围为-2147483648~2147483647(大约21亿左右),溢出后会导致报错。

67.【建议】业务中选择性很少的状态status、类型type等字段推荐使用tinytint或者smallint类型节省存储空间。

68.【建议】不推荐使用blob,text等类型。它们都比较浪费硬盘和内存空间。在加载表数据时,会读取大字段到内存里从而浪费内存空间,影响系统性能。建议和PM、RD沟通,是否真的需要这么大字段。Innodb中当一行记录超过8098字节时,会将该记录中选取最长的一个字段将其768字节放在原始page里,该字段余下内容放在overflow-page里。不幸的是在compact行格式下,原始page和overflow-page都会加载。

分库分表、分区表

69.【强制】分区表的分区字段(partition-key)必须有索引,或者是组合索引的首列。

70.【强制】上线前RD或者DBA必须指定分区表的创建、清理策略。

71.【强制】访问分区表的SQL必须包含分区键。

72.【建议】单个分表不超过500W行,ibd文件大小不超过2G,这样才能让数据分布式变得性能更佳。

73.【建议】水平分表尽量用取模方式,日志、报表类数据建议采用日期进行分表。

74.【强制】SELECT语句必须指定具体字段名称,禁止写成*。因为select *会将不该读的数据也从MySQL里读出来,造成网卡压力。且表字段一旦更新,但model层没有来得及更新的话,系统会报错。 mybatis 是自动生成的所有字段 mapping

数据库操作

75.【建议】SELECT语句不要使用UNION,推荐使用UNION ALL,并且UNION子句个数限制在5个以内。因为union all不需要去重,节省数据库资源,提高性能。

76.【建议】in值列表限制在500以内。例如select… where userid in(….500个以内…),这么做是为了减少底层扫描,减轻数据库压力从而加速查询。

77.【建议】事务里批量更新数据需要控制数量,进行必要的sleep,做到少量多次。

78. 【强制】生产数据库中强烈不推荐大表上发生全表扫描,但对于100行以下的静态表可以全表扫描。查询数据量不要超过表行数的25%,否则不会利用索引。

79.【建议】索引列不要使用函数或表达式,否则无法利用索引。如where length(name)='Admin'或where user_id+2=10023。

80.【建议】减少使用or语句,可将or语句优化为union,然后在各个where条件上建立索引。如where a=1 or b=2优化为where a=1… union …where b=2, key(a),key(b)。

81.【建议】分页查询,当limit起点较高时,可先用过滤条件进行过滤。如select a,b,c from t1 limit 10000,20;优化为: select a,b,c from t1 where id>10000 limit 20;。

82.【建议】对于MySQL主从延迟严格敏感的select语句,请开启事务强制访问主库。

83.【建议】减少使用order by,和业务沟通能不排序就不排序,或将排序放到程序端去做。order by、group by、distinct这些语句较为耗费CPU,数据库的CPU资源是极其宝贵的。

84.【建议】包含了order by、group by、distinct这些查询的语句,where条件过滤出来的结果集请保持在1000行以内,否则SQL会很慢。

85.【高危】禁止使用关联子查询,如update t1 set … where name in(select name from user where…);效率极其低下。

86.【强制】禁止联表更新语句,如update t1,t2 where t1.id=t2.id…。

Java 编程规范 -- 易错精简版相关推荐

  1. Java进阶3 - 易错知识点整理(待更新)

    Java进阶3 - 易错知识点整理(待更新) 该章节是Java进阶2- 易错知识点整理的续篇: 在前一章节中介绍了 ORM框架,中间件相关的面试题,而在该章节中主要记录关于项目部署中间件,监控与性能优 ...

  2. JAVA编程规范总结

    JAVA编程规范总结: 1.编码规范好处: 1.减少维护成本和时间 2.增加可读性,方便自己和维护的技术人员二次改善 3.提高开发效率,团队协作 4.养成好习惯,提高自身修炼 2.命名规范: 1.尽量 ...

  3. 阿里巴巴Java开发规范线程池_阿里巴巴java编程规范.pdf

    阿里巴巴java编程规范 目录 一.编程规约1 (一) 命名规约1 (二) 常量定义3 (三) 格式规约4 (四) OOP 规约6 (五) 集合处理 10 (六) 并发处理 12 (七) 控制语句 1 ...

  4. Java编程规范(一)

    Java编程规范 编程规约 命名风格 常量定义 代码格式 OOP约束 来源:阿里巴巴 编程规约 命名风格 不能以下划线或者美元符号开始或结束 **反例**:_name / __name / $name ...

  5. sun公司java编程规范【转载】

    java编程规范要学习的大致内容有如下部分,一个目录: Java编码规范 1 1.说明 3 1.1为什么要有编码规范 3 1.2版权声明 3 2.文件名(File Names) 3 2.1文件后缀(F ...

  6. java编程规范换行_Java编程规范整理

    近期即将开始编码阶段,特地整理一下各方面的编程规范与命名约定,以便内部团队风格统一. 文章大多从网络上收集汇总而来,参考列表附在文章末尾. Java编程规范整理 基本命名规范 包命名 包名按照域名的范 ...

  7. java8.0 platform图_Java Platform SE binary语言-Java编程32位/64位版(jdk-jeb)下载V8.0.2510.8官方安装版-西西软件下载...

    Java编程32位/64位版(jdk-jeb)是一款功能强大的计算机编程语言工具,Java技术让您可以在安全的计算环境下工作和游戏.使用 Java您可以畅玩网络游戏.与世界各地的朋友聊天.计算按揭利息 ...

  8. java 标识变量_Java变量与数据类型之一:Java编程规范,关键字与标识符

    原标题:Java变量与数据类型之一:Java编程规范,关键字与标识符 大家好,这次要给大家带来的是Java变量与数据类型.本文是第一集:Java编程规范,关键字与标识符. 一.编程规范 任何地方的名字 ...

  9. java与数据类型相关的十个关键字_乐字节Java变量与数据类型之一:Java编程规范,关键字与标识符...

    大家好,这次要给大家带来的是Java变量与数据类型.本文是第一集:Java编程规范,关键字与标识符. 一.编程规范 任何地方的名字都需要见名知意: 代码适当缩进 书写过程成对编程 对代码进行合理注释 ...

最新文章

  1. imrot matlab,Matlabtuxiangpipei
  2. java.getRunTime.exe
  3. C语言 · 分糖果
  4. linux 8g内存 swap,linux可用内存足够为什么还用swap
  5. ArcGIS Desktop新建postgresql版sde(10.4.1)的连接
  6. 使用wowza和xuggler将RTMP转换为RTSP
  7. 局域网抢答器_基于童芯派的抢答器V1.0
  8. ctfmon是什么启动项_启动项里ctfmon是什么意思,干什么用的??
  9. Windows7 共享文件夹不能访问(原创)
  10. Unity 获得某个物体的主贴图
  11. python编程机械_机器人Python编程与开发
  12. 文本在线查重(Online Copy Detection)的实现
  13. 编写WPF应用程序实现以下功能:定义一个RandomHelp类,该类提供一个静态的GetIntRandomNumber方法,一个静态的GetDoubleRandomNumber方法。
  14. 详解百度大脑EdgeBoard出色的视频处理技术
  15. SofaRpc源码学习篇-netty以及跟dubbo骚操作,负载均衡
  16. CNKI知网如何批量下载论文
  17. 2021年5月—系统集成项目管理工程师—上午综合知识(51-60)
  18. 英国帝国理工出品——SSIM对抗攻击
  19. python 同时输出国际和国内BMI值
  20. TTS(TextToSpeach)语音朗读实例

热门文章

  1. 脑机接口中的流形嵌入知识迁移学习
  2. 解决谷歌浏览器下载缓慢问题
  3. 吊打 CLIP 平均10个点,Meta 多模态通用模型 FLAVA真香啊
  4. Word2003入门动画教程25:添加或改变Word页面边框
  5. UI设计教程分享之RGB与CMYK色彩模式对比
  6. 替换请求输出文件和日志文件
  7. IDES安装之后的配置
  8. 用Python中的Numpy实现简单高效的扑克牌API(附代码)
  9. python--log日志的写法和介绍
  10. HadoopHA部署(1+x)