文档
锁
- 在锁冲突较小的时候,使用乐观锁可以大大增加性能(减少类锁的开销),但是当并发较高,锁冲突特别严重的时候,由于乐观锁需要不断重试,反而会降低性能。另外,乐观锁不仅仅可以使用version字段,也可以使用时间戳,或数据库列字段等任何可以判断数据是否被修改的字段。乐观锁字段按具体业务选择,可增加并发性能,以version字段作为乐观锁,每次只能有一个事务更新成功,会造成大量操作失败,互不冲突的更新操作,宜使用不同的字段作为乐观锁。
乐观锁
- 乐观锁是根据数据库的一个字段,在更新的时候判断数据有没有被改变。sql脚本类似如下:
update user set name='admin', version=version+1 where id='1' and version=1;
缓存
默认特性
- 映射语句文件中的所有 select 语句将会被缓存。
- 映射语句文件中的所有 insert,update 和 delete 语句会刷新缓存。
- 缓存会使用 Least Recently Used(LRU,最近最少使用的)算法来收回。
- 根据时间表(比如 no Flush Interval,没有刷新间隔), 缓存不会以任何时间顺序 来刷新。
- 缓存会存储列表集合或对象(无论查询方法返回什么)的 1024 个引用。
- 缓存会被视为是 read/write(可读/可写)的缓存,意味着对象检索不是共享的,而 且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改
实现原理
缺点
- 由于二级缓存是在namespace下的,当在不同的namespace下修改数据库时,会导致数据一致性问题。而且当namespace下进行delete,update时,会刷新namespace下所有数据。
缺陷避免
插件
问题
- 报错 org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.builder.xml.IncompleteStatementException: Could not find parameter map java.util.Map
解决:搜索文件*.xml 搜索词: parameterMap 然后将parameterMap 改为parameterType
缓存问题
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CacheData {
/**
* 缓存key前缀
*
* @return
*/
String value() default "";
}
import com.roncoo.pay.common.core.cache.key.CacheKey;
import com.roncoo.pay.common.core.cache.redis.RedisUtils;
import com.roncoo.pay.service.annotation.CacheData;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Slf4j
@Aspect
@Component
public class CacheDataAspect {
@Pointcut("@annotation(com.xxx.pay.service.annotation.CacheData)")
public void cacheDataAspect() {
}
@Around(value = "@annotation(cacheData)")
public Object around(ProceedingJoinPoint joinPoint, CacheData cacheData) throws Throwable {
log.debug("cacheData注解切面执行,{}{}", joinPoint.getThis(), cacheData.value());
String cacheKey = cacheData.value();
Object[] args = joinPoint.getArgs();
for (int i = 0; i < args.length; i++) {
cacheKey = cacheKey + CacheKey.KEY_SEPARATOR + args[i];
}
log.debug("cacheData切面获得缓存Key: {}", cacheKey);
Object value = RedisUtils.get(cacheKey);
log.debug("cacheData切面获得缓存数据:{}", value);
if (value != null) {
log.debug("cacheData切面获得缓存数据不为空,直接返回");
return value;
}
value = joinPoint.proceed();
log.debug("cacheData切面从方法查询数据:{}", value);
if (value != null) {
log.debug("cacheData切面从方法查询数据不为空,保存数据到redis中");
RedisUtils.save(cacheKey, value);
}
return value;
}
}
@CacheData("profix")