其他分享
首页 > 其他分享> > 大型项目技术栈第十讲 日志与性能监控

大型项目技术栈第十讲 日志与性能监控

作者:互联网

大型项目技术栈第十讲 日志与性能监控

一、事务管理策略

什么是事务?

事务是逻辑上的一组操作,要么都执行,要么都不执行。

事务最经典也经常被拿出来说例子就是转账了。假如小明要给小红转账1000元,这个转账会涉及到两个关键操作就是:将小明的余额减少1000元,将小红的余额增加1000元。万一在这两个操作之间突然出现错误比如银行系统崩溃,导致小明余额减少而小红的余额没有增加,这样就不对了。事务就是保证这两个关键操作要么都成功,要么都要失败。

事物的四大特性(ACID)介绍一下?

在这里插入图片描述

并发事务带来哪些问题?

在典型的应用程序中,多个事务并发运行,经常会操作相同的数据来完成各自的任务(多个用户对统一数据进行操作)。并发虽然是必须的,但可能会导致以下的问题:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

不可重复度和幻读区别:

不可重复读的重点是修改,幻读的重点在于新增或者删除。

例1(同样的条件, 你读取过的数据, 再次读取出来发现值不一样了 ):事务1中的A先生读取自己的工资为 1000的操作还没完成,事务2中的B先生就修改了A的工资为2000,导 致A再读自己的工资时工资变为 2000;这就是不可重复读。

例2(同样的条件, 第1次和第2次读出来的记录数不一样 ):假某工资单表中工资大于3000的有4人,事务1读取了所有工资大于3000的人,共查到4条记录,这时事务2 又插入了一条工资大于3000的记录,事务1再次读取时查到的记录就变为了5条,这样就导致了幻读。

事务隔离级别有哪些?MySQL的默认隔离级别是?

SQL 标准定义了四个隔离级别:

隔离级别 脏读 不可重复读 幻影读
READ-UNCOMMITTED
READ-COMMITTED ×
REPEATABLE-READ × ×
SERIALIZABLE × × ×

MySQL InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读)。我们可以通过SELECT @@tx_isolation;命令来查看

show variables;#查看所有数据库变量
select @@tx_isolation;#检索变量tx_isolation的值   @@表示检索变量

这里需要注意的是:与 SQL 标准不同的地方在于InnoDB 存储引擎在 **REPEATABLE-READ(可重读)事务隔离级别下使用的是Next-Key Lock 锁算法,因此可以避免幻读的产生,这与其他数据库系统(如 SQL Server)是不同的。所以说InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读) 已经可以完全保证事务的隔离性要求,即达到了 SQL标准的SERIALIZABLE(可串行化)**隔离级别。

模拟脏读

打开mysql客户端A,查看隔离级别

在这里插入图片描述

客户端A设置事务隔离级别

在这里插入图片描述

客户端B设置事务隔离级别

在这里插入图片描述

客户端A关闭事务自动提交,开启事务

在这里插入图片描述

客户端B关闭事务自动提交,开启事务

在这里插入图片描述

客户端A查询一条记录

在这里插入图片描述

客户端B修改该记录

在这里插入图片描述

客户端A再次查询该记录,出现脏读:

在这里插入图片描述

二、druid性能监控

1.Druid的监控统计功能页面效果

在这里插入图片描述

2.1.打开监控功能

Druid内置提供一个StatFilter,用于统计监控信息。

(参考文档:https://github.com/alibaba/druid/wiki/%E9%85%8D%E7%BD%AE_StatFilter

2.1.1. 别名配置

StatFilter的别名是stat,这个别名映射配置信息保存在druid-xxx.jar!/META-INF/druid-filter.properties。

在spring中使用别名配置方式如下:

//如果Properties文件的属性名命名符合configFromPropety的参数Properties的命名规则,则自动赋值
@Bean
public DruidDataSource getDataSource(){
    Properties props = new Properties();
    try {
        props.load(SpringMybatisConfig.class.getClassLoader().getResourceAsStream("db.properties"));
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.configFromPropety(props);
        dataSource.setFilters("stat");//配置默认监控filter
        return dataSource;
    } catch (IOException e) {
        e.printStackTrace();
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return null;
}

2.1.2. 组合配置

StatFilter可以和其他的Filter配置使用,比如:

//如果Properties文件的属性名命名符合configFromPropety的参数Properties的命名规则,则自动赋值
@Bean
public DruidDataSource getDataSource(){
    Properties props = new Properties();
    try {
        props.load(SpringMybatisConfig.class.getClassLoader().getResourceAsStream("db.properties"));
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.configFromPropety(props);
        dataSource.setFilters("stat,wall,slf4j");
        dataSource.setConnectionProperties("druid.stat.mergeSql=true;druid.stat.slowSqlMillis=1000");//开启慢sql监控,大于1000毫秒的为慢sql,默认是3秒
        return dataSource;
    } catch (IOException e) {
        e.printStackTrace();
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return null;
}

在上面的配置中,StatFilter和WallFilter、SlfFilter组合使用。

WallFilter:防止sql注入的过滤器

(参考文档:https://github.com/alibaba/druid/wiki/%E9%85%8D%E7%BD%AE-wallfilter

Slf4jFileter:日志记录JDBC执行的SQL

(参考文档:https://github.com/alibaba/druid/wiki/配置_LogFilter)

2.2使用Druid的内置监控页面

要访问druid的内置监控页面,需要配置一个servlet(参考文档:https://github.com/alibaba/druid/wiki/配置_StatViewServlet配置)

@WebServlet(urlPatterns = "/druid/*",initParams = {
        @WebInitParam(name="allow",value = ""),//ip白名单,没有配置或空,则允许所有访问
        @WebInitParam(name="deny",value = ""),//ip黑名单
        @WebInitParam(name = "loginUsername",value = "admin"),//用户名
        @WebInitParam(name="loginPassword",value = "123456"),//密码
        @WebInitParam(name="resetEnable",value="false")//禁用html页面的reset all功能
})
public class DruidStatueServlet extends StatViewServlet {
    
}

或者在spring配置类中:

/**     * 注册一个StatViewServlet     *     * @return     */    @Bean    public ServletRegistrationBean druidServlet() {        ServletRegistrationBean reg = new ServletRegistrationBean();        reg.setServlet(new StatViewServlet());        reg.addUrlMappings(new String[]{"/druid/*"});        //IP白名单 (没有配置或者为空,则允许所有访问)        reg.addInitParameter("allow", "");        //是否能够重置数据        reg.addInitParameter("resetEnable", "false");        //设置账号密码        reg.addInitParameter("loginUsername", "admin");        reg.addInitParameter("loginPassword", "123456");        return reg;    }

开启后即可以启动服务器,并且通过地址栏访问监控页面,访问规则:

ip:端口号/应用名/druid/login.html

在这里插入图片描述

输入上一步设置的账户密码即可登录

3.设置web监控

WebStatFilter用于采集web-jdbc关联监控的数据(参考文档:https://github.com/alibaba/druid/wiki/配置_配置WebStatFilter)

@WebFilter(filterName = "druidStatueFilter",urlPatterns = "/*",
        initParams = {
        @WebInitParam(name="exclusions",value = "*.js,*.jpg,*.png,*.css,/druid/*"),
        @WebInitParam(name="profileEnable",value = "true")
})
public class DruidStatueFilter extends WebStatFilter {

}

或者在spring配置类中:

/**
     * 注册一个:filterRegistrationBean
     *
     * @return
     */
    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(new WebStatFilter());
        //添加过滤规则
        filterRegistrationBean.addUrlPatterns(new String[]{"/*"});
        //添加需要忽略的格式信息
        filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
        filterRegistrationBean.addInitParameter("profileEnable", "true");//配置profileEnable能够监控单个url调用的sql列表
        filterRegistrationBean.addInitParameter("principalCookieName", "USER_COOKIE");//如果你的user信息保存在cookie中,你可以配置
//principalCookieName,使得druid知道当前的user是谁  USER_COOKIE为cookie名
        filterRegistrationBean.addInitParameter("principalSessionName", "USER_SESSION");//使得druid能够知道当前的session的用户是谁
        filterRegistrationBean.addInitParameter("DruidWebStatFilter", "/*");
        return filterRegistrationBean;
    }

4.设置spring监控

@Bean(name="druidStatInterceptor")//设置druid 的 aop切面类
public DruidStatInterceptor getDruidStatInterceptor(){
    DruidStatInterceptor druidStatInterceptor = new DruidStatInterceptor();

    return druidStatInterceptor;
}


@Bean//配置spring监控
public BeanNameAutoProxyCreator getAutoProxyCreator(){
    BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
    beanNameAutoProxyCreator.setProxyTargetClass(true);
    beanNameAutoProxyCreator.setBeanNames(new String[]{"*Mapper","*Service"});
    beanNameAutoProxyCreator.setInterceptorNames("druidStatInterceptor");
    return beanNameAutoProxyCreator;
}

标签:事务,大型项目,隔离,第十,幻读,filterRegistrationBean,druid,new,日志
来源: https://blog.51cto.com/u_14627411/3044718