周五调试线上环境的应用,发现某个服务响应时间非常慢,以正常情况衡量,一般每个请求处理时间大概在500ms以内,但是该请求处理时间长达3~5秒
线上应用的大致情况为:该应用为一个运营支撑系统,主要处理运营数据的推送和查询,ORM 采用ibatis框架,日志使用log4j。
针对响应时间较长的请求进行调试(还好日志跟踪比较全面),该请求包含多个业务处理,在某个日志区间,发现处理时间跨度竟然在3-5秒,应该就是这个区间的处理时间长,导致请求响应速度下降。
大致分析了下该区间的处理,基本排除业务处理代码的性能瓶颈,定位是某个数据库查询SQL操作耗时长。但是ibatis在该SQL上设置了缓存,查询了某个配置表的全部数据,然后做全表缓存。理论上应该是初次查询速度较慢(这个可以接受),但是后续的请求应该全部命中缓存,不会再有数据库查询。通过DBA的协助,线上数据库也未发现该数据表的查询,说明后续的查询请求确实命中了缓存。
使用jprofiler进行cpu的处理时间的剖析,发现主要问题还是和业务的处理方式有关,在使用缓存的方式上存在一定的偷懒,过于依赖程序的处理速度,为了节省数据库查询,一次将数据库表中的数据(近8w条)全部查询出来,并用一个key进行缓存,众所周知ibtais是基于查询的缓存而非对象,因此缓存的数据量较大时,下一次的查询在通过cache获取数据时会带来大量的性能消耗,如下:
CacheModel.getObject用来根据key从缓存取数据(这里缓存了一个仅8w多个数据对象的hashmap)
if ( log.isDebugEnabled() ) {
if ( value != null ) {
log("retrieved object", true, value);
}
else {
log("cache miss", false, null);
}
}
由于存在上诉代码,会存在将这个8w多个数据对象进行toString()的过程,虽然每个对象toString 的时间在 微秒级别,但是由于数据量较大,总的耗时较长
avg:27us , 88404次的invoke,总耗时2s多
当然也可以通过修改日志级别来解决问题
private static final Log log = LogFactory.getLog(CacheModel.class);
为该logger指定日志级别,避免CacheModel.getObject中log方法的调用
********************************************************************
对于未声明的logger,LogFactory会创建一个
level=null,
parentLogger=org.apache.log4j.spi.RootLogger
的logger
见如下代码
Log instance = (Log) instances.get(name);
if (instance == null) {
instance = newInstance(name);
instances.put(name, instance);
}
当ibatis调用 log.isDebugEnabled() 时,先判断当前logger的level,为空继续判断parentlogger的level,org.apache.log4j.spi.RootLogger默认level为debug,见如下代码
Hierarchy h = new Hierarchy(new RootLogger((Level) Level.DEBUG));
就会导致获取每个缓存object都会调用一次log记录
********************************************************************
但是这么大的数据量放在那里,无论做排除或者做筛选,无论业务处理 or ORM 框架处理,都会导致总耗时超长的情况
因此在使用ibatis的缓存时,要明白基于查询的缓存,是否缓存的数据量会较大,尽量避免一次查询缓存多条数据,尽量将缓存数据根据查询条件分拆到多个key中,提升处理性能。
- 大小: 7.6 KB
- 大小: 3.2 KB
分享到:
相关推荐
总的来说,iBATIS缓存是优化数据库操作性能的有效手段,但同时也需要谨慎使用,合理配置缓存策略,防止出现因缓存导致的数据不一致问题。了解和掌握iBATIS缓存的原理与实践,能帮助开发者更好地优化应用程序,提升...
在实际应用中,我们可以通过以下方式配置和使用iBatis缓存: - **启用二级缓存**:在MyBatis的配置文件中启用全局缓存,并在Mapper接口的XML配置文件中添加`<cache>`标签,指定缓存策略。 - **自定义缓存实现**:若...
6. **缓存机制**:Ibatis提供了本地缓存和二级缓存,可以提高数据访问速度,但需要根据项目需求谨慎配置和使用。 7. **事务控制**:Ibatis可以与Spring等框架集成,实现基于编程或声明式的事务管理。 8. **Mapper...
因此,在高并发环境下使用二级缓存时,需要谨慎设计和优化。 通过以上讲解,你应该对iBatis的一级缓存和二级缓存有了基础认识。在实际项目中,根据业务需求合理选择和配置缓存,能够显著提升系统的响应速度和资源...
此外,iBatis还提供了缓存机制,能够提高数据访问速度,但需谨慎使用,以免引发数据一致性问题。 学习iBatis的过程中,理解它的异常处理机制也是必要的。当SQL执行出错时,iBatis会抛出特定的异常,如`...
标题中的“自定义Ibatis生成器”指的是在使用MyBatis框架时,为了解决重复的手动编写SQL映射文件和Mapper接口,开发者可以创建自己的代码生成器,以自动化这个过程。Ibatis生成器(也称为MyBatis Generator)允许...
但需要注意的是,缓存的使用需要谨慎,避免引发数据一致性问题。 8. 事务管理:Ibatis允许你在SqlMapConfig.xml中配置事务管理器,可以与Spring等框架集成,实现声明式事务管理。 综上所述,Ibatis文档及demo包含...
- **缓存管理**:启用二级缓存可以提高查询效率,但需要谨慎处理并发问题和数据一致性。 - **批处理**:使用`<foreach>`标签批量处理插入、更新和删除操作,减少数据库连接的开销。 - **结果映射优化**:合理使用...
因此,需要谨慎使用,并确保只在确实需要时才触发关联数据的加载。 4. **Eager Fetching(预加载)**: 相反于延迟加载,预加载是在主对象加载时同时加载关联数据。在iBATIS中,可以通过配置映射文件来指定预加载...
JavaEE环境下的ORM框架如Hibernate、iBatis(现称为MyBatis)、TopLink、JDO、JPA等,旨在简化数据访问层的编码工作,提高开发效率和代码的可维护性。 ORM框架的核心原理在于读取配置文件,自动关联JavaBean的属性...
- **缺点:**学习曲线较陡峭,对内存使用和性能的影响需要谨慎评估。 ### 应用场景与选择 IBatisNet更适合那些需要精细控制SQL执行,或者对数据库操作有特殊要求的项目。而NHibernate则适用于大型项目,尤其是那些...
缓存可以有效地减少对数据库的访问,提高性能,但需谨慎使用,避免数据一致性问题。 8. **MyBatis与Spring整合**:在大型项目中,MyBatis通常与Spring框架集成,利用Spring的依赖注入和事务管理功能。通过`@...
17. **反射机制**:运行时动态访问类信息,创建对象,调用方法等,但应谨慎使用以避免性能损失。 18. **Spring框架**:核心特性是IOC(控制反转)和AOP(面向切面编程),广泛应用于现代Java项目。 19. **线程同步...
SQL映射的XML文件部分则涵盖了select、insert、update和delete等基本SQL操作标签的使用方法,还包括了高级结果映射的配置、支持的JDBC类型、构造方法、关联、集合、鉴别器、缓存等高级特性。动态SQL的构建是MyBatis...
缓存的配置和使用需要谨慎,以避免数据一致性问题。 七、事务管理 Mybatis 的事务管理可以通过编程式或声明式实现。编程式事务管理需要在代码中手动开启和提交事务,声明式事务管理则依赖于 Spring 等框架来处理。 ...