阿里巴巴手册
2021-04-18 14:44:10 0 举报
AI智能生成
泰山版阿里巴巴java手册
作者其他创作
大纲/内容
并发处理
1.【强制】 获取单例对象需要保证线程安全,其中的方法也要保证线程安全
2. 【强制】 创建线程或线程池时请指定有意义的线程名称,方便出错时回溯
3. 【强制】 线程资源必须通过线程池提供,不允许在应用中自行显式创建线程
4. 【强制】 线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这<br>样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
5. 【强制】 SimpleDateFormat 是线程不安全的类,一般不要定义为 static 变量,如果定义为 static,<br>必须加锁,或者使用 DateUtils 工具类。
6. 【强制】 必须回收自定义的 ThreadLocal 变量,尤其在线程池场景下,线程经常会被复用,<br>如果不清理自定义的 ThreadLocal 变量,可能会影响后续业务逻辑和造成内存泄露等问题。<br>尽量在代理中使用 try-finally 块进行回收。
7. 【强制】 高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁; 能锁区块,就不要锁整个方法体; 能用对象锁,就不要用类锁。<br>
8. 【强制】 对多个资源、数据库表、对象同时加锁时,需要保持一致的加锁顺序,否则可能会造成死锁。
9. 【强制】 在使用阻塞等待获取锁的方式中,必须在 try 代码块之外,并且在加锁方法与 try 代码块之间没有任何可能抛出异常的方法调用,避免加锁成功后,在 finally 中无法解锁。
10. 【强制】 在使用尝试机制来获取锁的方式中,进入业务代码块之前,必须先判断当前线程是否持有锁。锁的释放规则与锁的阻塞等待方式相同
11.【强制】 并发修改同一记录时,避免更新丢失, 需要加锁。 要么在应用层加锁,要么在缓存加锁,要么在数据库层使用乐观锁,使用 version 作为更新依据。
12.【强制】 多线程并行处理定时任务时, Timer 运行多个 TimeTask 时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行, 使用 ScheduledExecutorService 则没有这个问题。
13.【推荐】 资金相关的金融敏感信息,使用悲观锁策略。<br>说明: 乐观锁在获得锁的同时已经完成了更新操作,校验逻辑容易出现漏洞,另外,乐观锁对冲突的解决策略有较复杂的要求,处理不当容易造成系统压力或数据异常,所以资金相关的金融敏感信息不建议使用乐观锁更新。
14.【推荐】 使用 CountDownLatch 进行异步转同步操作,每个线程退出前必须调用 countDown 方法,线程执行代码注意 catch 异常,确保 countDown 方法被执行到,避免主线程无法执行至await 方法,直到超时才返回结果。
15.【推荐】避免 Random 实例被多线程使用,虽然共享该实例是线程安全的,但会因竞争同一 seed导致的性能下降
16.【推荐】 通过双重检查锁( double-checked locking) ( 在并发场景下) 实现延迟初始化的优化问题隐患(可参考 The "Double-Checked Locking is Broken" Declaration), 推荐解决方案中较为简单一种( 适用于 JDK5 及以上版本) ,将目标属性声明为 volatile 型( 比如修改 helper 的属性声明为`private volatile Helper helper = null;`)
<font color="#c41230">17.【参考】 volatile 解决多线程内存不可见问题。对于一写多读,是可以解决变量同步问题,但是如果多写,同样无法解决线程安全问题</font>。
18.【参考】 HashMap 在容量不够进行 resize 时由于高并发可能出现死链,导致 CPU 飙升,在开发过程中注意规避此风险
19.【参考】 ThreadLocal 对象使用 static 修饰, ThreadLocal 无法解决共享对象的更新问题。
Mysql数据库
(二) 索引规约
1. 【强制】 业务上具有唯一特性的字段,即使是组合字段,也必须建成唯一索引
2. 【强制】 超过三个表禁止 join。需要 join 的字段,数据类型保持绝对一致; 多表关联查询时,保证被关联的字段需要有索引
3. 【强制】 在 varchar 字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据实际文本区分度决定索引长度
4. 【强制】 页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决。
5. 【推荐】 如果有 order by 的场景,请注意利用索引的有序性。 order by 最后的字段是组合索引的一部分,并且放在索引组合顺序的最后,避免出现 file_sort 的情况,影响查询性能。
6. 【推荐】 利用覆盖索引来进行查询操作, 避免回表。<br>说明: 如果一本书需要知道第 11 章是什么标题,会翻开第 11 章对应的那一页吗?目录浏览一下就好,这个目录就是起到覆盖索引的作用。
<b><font color="#c41230">7. 【推荐】 利用延迟关联或者子查询优化超多分页场景</font></b>。
8. 【推荐】 SQL 性能优化的目标:至少要达到 range 级别, 要求是 ref 级别, 如果可以是 consts最好。<br>
9. 【推荐】 建组合索引的时候,区分度最高的在最左边。
10.【推荐】 防止因字段类型不同造成的隐式转换, 导致索引失效。
11.【参考】 创建索引时避免有如下极端误解:
(三) SQL 语句<br>
<font color="#c41230">1. 【强制】 不要使用 count(列名)或 count(常量)来替代 count(*), count(*)是 SQL92 定义的标准统计行数的语法,跟数据库无关,跟 NULL 和非 NULL 无关</font>
2. 【强制】count(distinct col) 计算该列除 NULL 之外的不重复行数,注意 count(distinct col1,col2) 如果其中一列全为 NULL,那么即使另一列有不同的值,也返回为 0
3. 【强制】 当某一列的值全是 NULL 时, count(col)的返回结果为 0,但 sum(col)的返回结果为NULL,因此使用 sum()时需注意 NPE 问题<br>
<b><font color="#381e11">4. 【强制】 使用 ISNULL()来判断是否为 NULL 值</font></b>。
5. 【强制】 代码中写分页查询逻辑时,若 count 为 0 应直接返回,避免执行后面的分页语句。
6. 【强制】 不得使用外键与级联,一切外键概念必须在应用层解决。
7. 【强制】 禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。
8. 【强制】 数据订正(特别是删除或修改记录操作) 时,要先 select,避免出现误删除,确认无误才能执行更新语句。
9. 【强制】 对于数据库中表记录的查询和变更,只要涉及多个表,都需要在列名前加表的别名(或表名)进行限定。
10.【推荐】 SQL 语句中表的别名前加 as,并且以 t1、 t2、 t3、 ...的顺序依次命名。
11.【推荐】 in 操作能避免则避免,若实在避免不了,需要仔细评估 in 后边的集合元素数量,控制在 1000 个之内
12.【参考】 因国际化需要,所有的字符存储与表示,均采用 utf8 字符集, 那么字符计数方法需要注意
13.【参考】 TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源少,但 TRUNCATE无事务且不触发 trigger,有可能造成事故,故不建议在开发代码中使用此语句。
(四) ORM 映射<br>
1. 【强制】 在表查询中,一律不要使用 * 作为查询的字段列表,需要哪些字段必须明确写明。
2. 【强制】 POJO 类的布尔属性不能加 is,而数据库字段必须加 is_,要求在 resultMap 中进行字段与属性之间的映射
3. 【强制】 不要用 resultClass 当返回参数,即使所有类属性名与数据库字段一一对应,也需要<br>定义<resultMap>;反过来,每一个表也必然有一个<resultMap>与之对应。
4. 【强制】 sql.xml 配置参数使用: #{}, #param# 不要使用${} 此种方式容易出现 SQL 注入
5. 【强制】 iBATIS 自带的 queryForList(String statementName,int start,int size)不推荐使用
6. 【强制】 不允许直接拿 HashMap 与 Hashtable 作为查询结果集的输出
7. 【强制】 更新数据表记录时,必须同时更新记录对应的 gmt_modified 字段值为当前时间
8. 【推荐】 不要写一个大而全的数据更新接口。 传入为 POJO 类,不管是不是自己的目标更新字段,都进行 update table set c1=value1,c2=value2,c3=value3; 这是不对的。执行 SQL 时,不要更新无改动的字段,一是易出错;二是效率低;三是增加 binlog 存储
9. 【参考】 <span class="tag">@Transactional</span> 事务不要滥用。事务会影响数据库的 QPS,另外使用事务的地方需要考虑各方面的回滚方案,包括缓存回滚、搜索引擎回滚、消息补偿、统计修正等。
10.【参考】 <isEqual>中的 compareValue 是与属性值对比的常量,一般是数字,表示相等时带上此条件; <isNotEmpty>表示不为空且不为 null 时执行; <isNotNull>表示不为 null 值时执行
集合处理
1. 【强制】 关于 hashCode 和 equals 的处理,遵循如下规则
2. 【强制】 判断所有集合内部的元素是否为空,使用 isEmpty()方法,而不是 size()==0 的方式。
3. 【强制】 在使用 java.util.stream.Collectors 类的 toMap()方法转为 Map 集合时,一定要使<br>用含有参数类型为 BinaryOperator,参数名为 mergeFunction 的方法,否则当出现相同 key<br>值时会抛出 IllegalStateException 异常。
服务器设置
1. 【推荐】 高并发服务器建议调小 TCP 协议的 time_wait 超时时间。
2. 【推荐】 调大服务器所支持的最大文件句柄数( File Descriptor,简写为 fd) 。
3 【推荐】给 JVM 环境参数设置-XX:+HeapDumpOnOutOfMemoryError 参数,让 JVM 碰到 OOM场景时输出 dump 信息。
4. 【推荐】 在线上生产环境, JVM 的 Xms 和 Xmx 设置一样大小的内存容量, 避免在 GC 后调整堆大小带来的压力
<font color="#c41230">5. 【参考】 服务器内部重定向必须使用 forward; 外部重定向地址必须使用 URL Broker 生成, 否则因线上采用 HTTPS 协议而导致浏览器提示“不安全“。此外,还会带来 URL 维护不一致的问题</font>
0 条评论
下一页