• 分布式事务03单体应用分库多数据源改造


    需要多库的原因

    什么情况下需要多库呢?数据库不够用的时候。

    如果应用的用户不断增长,数据量也不断增长,单一数据库的数据量较大(问题来了,多少算较大?),数据库查询成了瓶颈的时候,那么就需要分库分表。

    数据量推测

    假设是流量充值应用场景。

    假设100万注册用户

    访问量:一天3万次流量充值

    调用接口最少数量:

    1. 进入流量充值界面
    2. 显示流量充值的金额
    3. 完成支付

    可以假设,每天调用的次数最少为:3万次 * 3 = 9万次接口的调用,认为一天大约10万次接口调用。

    高峰时期调用数量

    高峰时间段:中午2小时,晚上2小时,假设一天高峰是4小时。

    高峰承载量:假设承载80%的请求数量,即10万 * 80% = 8万次。

    高峰每秒请求次数:每小时2万次调用,2万 / 3600 = 5.5,大约5/s。

    高峰数据库写入量:以订单数计算,一天3万条,一个月150万数据,一年就是2000万订单数据

    假设1000万注册用户

    假设就是100万用户放大十倍,那么每年至少2亿订单数据。

    当用户量更大的时候,数据量更大,数据库访问不是瓶颈,但是数据库的空间大小成为瓶颈。

    数据拆分

    一般而言,是按照数据量分库分表,把数据量均匀分布到多个数据库中。
    但刚开始就以最简单的按业务来拆分库。

    资金、流量券、促销、积分、流量套餐、抽奖、充值订单,分别使用独立的数据库服务器,各个表的数据放在自己的服务器上,使用自己的磁盘空间,这样可以初步的先延长一下我们数据库的使用的周期。

    单体应用多数据源改造

    1. 根据业务先建立多个库,再把每个业务对应的表移过去
    2. 设置多个数据源
    3. 把mapper分到各个package里
    4. 在application.yml中,配置相应的参数,便于@Value("${activity.datasource.url}") 获取到参数
    5. 配置mapperscan
    6. @Bean(name = "activityTransactionManager")
    7. @Primary 这个注解只要一个bean写,不写或者在多个配置bean里写都不行

    改完测试功能是否完整

    @Configuration  
    @MapperScan(basePackages = "com.zhss.data.refill.center.mapper.activity", 
    			sqlSessionFactoryRef = "activitySqlSessionFactory")
    public class ActivityDataSourceConfig {  
       
        @Value("${activity.datasource.url}")  
        private String dbUrl;  
        @Value("${activity.datasource.username}")  
        private String username;  
        @Value("${activity.datasource.password}")  
        private String password;  
        @Value("${activity.datasource.driverClassName}")  
        private String driverClassName;  
        @Value("${activity.datasource.initialSize}")  
        private int initialSize;  
        @Value("${activity.datasource.minIdle}")  
        private int minIdle;  
        @Value("${activity.datasource.maxActive}")  
        private int maxActive;  
        @Value("${activity.datasource.maxWait}")  
        private int maxWait;  
        @Value("${activity.datasource.timeBetweenEvictionRunsMillis}")  
        private int timeBetweenEvictionRunsMillis;  
        @Value("${activity.datasource.minEvictableIdleTimeMillis}")  
        private int minEvictableIdleTimeMillis;  
        @Value("${activity.datasource.validationQuery}")  
        private String validationQuery;  
        @Value("${activity.datasource.testWhileIdle}")  
        private boolean testWhileIdle;  
        @Value("${activity.datasource.testOnBorrow}")  
        private boolean testOnBorrow;  
        @Value("${activity.datasource.testOnReturn}")  
        private boolean testOnReturn;  
        @Value("${activity.datasource.poolPreparedStatements}")  
        private boolean poolPreparedStatements;  
        @Value("${activity.datasource.maxPoolPreparedStatementPerConnectionSize}")  
        private int maxPoolPreparedStatementPerConnectionSize;  
        @Value("${activity.datasource.filters}")  
        private String filters;  
        @Value("${activity.datasource.connectionProperties}")  
        private String connectionProperties;  
        
        /**
         * 创建druid数据库连接池bean
         * @return
         */
        @Bean(name = "activityDataSource")     
        @Primary  
        public DataSource activityDataSource(){  
            DruidDataSource datasource = new DruidDataSource();  
            datasource.setUrl(this.dbUrl);  
            datasource.setUsername(username);  
            datasource.setPassword(password);  
            datasource.setDriverClassName(driverClassName);  
            datasource.setInitialSize(initialSize);  
            datasource.setMinIdle(minIdle);  
            datasource.setMaxActive(maxActive);  
            datasource.setMaxWait(maxWait);          
            datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);  
            datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);  
            datasource.setValidationQuery(validationQuery);  
            datasource.setTestWhileIdle(testWhileIdle);  
            datasource.setTestOnBorrow(testOnBorrow);  
            datasource.setTestOnReturn(testOnReturn);  
            datasource.setPoolPreparedStatements(poolPreparedStatements);  
            datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);  
            
            try {  
                datasource.setFilters(filters);  
            } catch (SQLException e) {  
                e.printStackTrace();
            }  
            
            datasource.setConnectionProperties(connectionProperties);  
              
            return datasource;  
        }
        
        @Bean(name = "activityTransactionManager")
        @Primary
        public DataSourceTransactionManager activityTransactionManager() {
        	return new DataSourceTransactionManager(activityDataSource());
        }
    
        @Bean(name = "activitySqlSessionFactory")
        @Primary
        public SqlSessionFactory activitySqlSessionFactory(
        		@Qualifier("activityDataSource") DataSource activityDataSource) throws Exception {
        	final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        	sessionFactory.setDataSource(activityDataSource);
        	return sessionFactory.getObject();
        }   
        
    }
    
  • 相关阅读:
    coco2d-js demo程序之滚动的小球
    【leetcode】Happy Number(easy)
    【leetcode】Remove Linked List Elements(easy)
    【leetcode】LRU Cache(hard)★
    【QT】计时器制作
    【leetcode】Min Stack(easy)
    【leetcode】Compare Version Numbers(middle)
    【leetcode】Excel Sheet Column Title & Excel Sheet Column Number (easy)
    【leetcode】Binary Search Tree Iterator(middle)
    【leetcode】Number of Islands(middle)
  • 原文地址:https://www.cnblogs.com/richardhaha/p/15807294.html
Copyright © 2020-2023  润新知