《Java工程师修炼之道》读书笔记-Part 1
《Java工程师修炼之道》读书笔记-Part 1
持续学习
敢于“逃离舒适区”、敢于使用新技术,这样才能让自己具有持续的学习兴趣,促进自己的持续进步。
知识收获整理成体系,或者融入自己的知识体系中。
下面是整理的部分感兴趣的知识点。
1. 分布式数据库中间件、产品——sharding-jdbc、mycat、drds
可以看出sharding-jdbc作为一个组件集成在应用内,而mycat则作为一个独立的应用需要单独部署,drds则是阿里云的一个独立产品,不过需要结合rds一起使用。
从架构上看sharding-jdbc更符合分布式架构的设计,直连数据库,没有中间应用,理论性能是最高的(实际性能需要结合具体的代码实现,理论性能可以理解为上限,通过不断优化代码实现,逐渐接近理论性能)。同时缺点也很明显,由于作为组件存在,需要集成在应用内,意味着作为使用方,必须要集成到代码里,使得开发成本相对较高;另一方面,由于需要集成在应用内,使得需要针对不同语言(java、C、PHP……)有不同的实现(事实上sharding-jdbc目前只支持java),这样组件本身的维护成本也会很高。最终将应用场景限定在由java开发的应用这一种场景下。
2. 软件开发的核心原则
Done is better than perfect.
在面对一个开发任务时,最佳的思路就是先把东西做出来,再去迭代优化。
Choose the most suitable things.
要选择最合适的技术,而不是盲目求新。
在互联网的开发工作中,敏捷开发是比较受推崇的开发方式。
所谓的敏捷开发,即快速实现原型,然后快速迭代。
项目工具:禅道 --是国人开发的一款项目管理工具,但是其免费版功能有限。
3. 负载均衡
LVS 是最流行的4层负载均衡软件,HAProxy 是另一个既支持4层,又支持7层负载均衡软件,Nginx 则是7层负载均衡最流行的解决方案。
4. Java 编程知识
集合类是Java语言非常精华的部分,包括HashMap、ArrayList、LinkedList、HashSet、TreeSet以及线程安全的ConcurrentHashMap、ConcurrentLinkedQueue等线程安全集合。
在使用基于数组的集合时,如ArrayList、HashMap时,必须指定初始化大小,否则大小不足时,会成倍扩容。
DateFormat 类以及其子类,都是非线程安全的,在多线程环境下不能使用单例。
主流构建工具-Maven
Maven 基于POM(Project Object Model)进行。一个项目所有的配置都放置在pom.xml文件中,包括定义项目的类型、名字、管理依赖关系,定制插件的行为等。
Maven 使用 groupId:artifactId:version 三者来标识一个唯一的二进制版本。
日志框架
目前比较推崇使用SLF4J 统一所有框架接口,然后都转换到Logback的底层实现。
如果是一个新项目,直接选择Log4j2 也是不错的选择。
5. Spring
Spring 的IoC容器是ApplicationContext。
上下文中的实例在Spring 中称为 Bean。
一个Bean 的生命周期。
无XML的配置方式
@Configuration 标识此类的用途是定义Bean;
@Bean 注解到方法上,创建、初始化一个Bean,对应于<beans /> 配置;
如果Bean 注解里面的name 为空,那么Bean 的id 为方法的名字。
@Import 允许将其他 JavaConfig 形式的配置类引入到当前的 @Configuration 标注的配置类当中。
如 @Import(SpringExtraConfig.class)
Spring Boot
目的是降低使用 Spring 的门槛。
大大简化了Spring 的配置工作,并且能够很容易地将应用打包为可独立运行的程序(即不依赖于第三方容器,可以独立以 jar 或者 war 包的形式运行)。
Spring Boot 启动
@SpringBootApplication 注解是一个复合注解,包括了@Configuration、@EnableAutoConfiguration以及@ComponentScan。
通过SpringApplication的run方法,Spring 就会使用该类作为Java 配置类来读取相关配置,加载和扫描相关的Bean。
Spring Boot 由很多模块组成,可以通过 POM 文件引入进来。@EnableAutoConfiguration 机制会进行插件化加载并自动配置。
6. MySQL 数据库
索引注意事项
(1)最左前缀原则
如果查询的时候,查询条件精确匹配索引的左边连续一列或几列,则可以命中索引。
(2)避免where 子句中对字段施加函数,如to_date(create_time)>xxxxxx,这样会造成无法命中索引。
(3)在使用InnoDB 时,使用与业务无关的自增主键作为主键,即使用逻辑主键,而不要使用业务主键。
(4)合理利用索引覆盖
覆盖索引(Covering index)指一个查询语句的执行,只需要从辅助索引中就可以得到查询记录,而不需要查询聚集索引中的记录,也可以称之为实现了索引覆盖。
简单来说,就是查询条件命中了索引,而查询字段也属于索引中的字段。
当实现了覆盖索引的时候,explain 命令的Extra 会显示 using Index。
(5)避免冗余索引
可以查询sys 库的schemal_redundant_indexes 表来查看冗余索引。
select * from sys.schema_redundant_indexes;
(6)将打算加索引的列设置为 NOT NULL,否则将导致引擎放弃使用索引,而进行全表扫描。
(7)删除长期未使用的索引
可以查询sys 库的 schema_unused_indexes 视图来查询从未使用过的索引。
select * from sys.schema_unused_indexes;
(8)联表查询,也可以使用索引:
- 确保 ON 和 USING 中列上有索引。
- 确保任何的 GROUP BY 和 ORDER BY 中的表达式只涉及一个表中列。
(9)查询条件的字段应使用正确的数据类型,否则MySQL 会自动做类型转换,导致无法命中索引。
索引的代价:
1. 索引文件本身要消耗存储空间;
2. 在被索引的表上,INSERT/DELETE 会变慢;
3. MySQL在运行时,也要消耗资源维护索引;
大表优化
- 读写分离;
- 缓存;
- 垂直分区;
优点在于可以使得行数据变小,在查询时减少读取的Block 数,减少I/O次数。
- 水平分区;
通过某种策略存储数据分片,如按照时间序列;
水平分区最好分库;
数据库分片方案
- 客户端代理
分片逻辑在应用端,封装在jar包中,通过修改或者封装JDBC 层来实现。Sharding-JDBC、阿里的TDDL实现方案。
- 中间件代理
在应用和数据中间加了一个代理层。分片的逻辑统一维护在中间件服务中。开源的MyCat和Kingshard 都是这种架构实现的。