亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

Table of Contents
2: Configuration of data source routing " >2: Configuration of data source routing
三:數(shù)據(jù)源上下文環(huán)境 " >三:數(shù)據(jù)源上下文環(huán)境
四:切換注解和 Aop 配置 " >四:切換注解和 Aop 配置
五:用法以及測試 " >五:用法以及測試
Home Java javaTutorial Spring Boot implements MySQL read-write separation technology

Spring Boot implements MySQL read-write separation technology

Aug 15, 2023 pm 04:52 PM
mysql spring boot

How to achieve read-write separation, Spring Boot project, the database is MySQL, and the persistence layer uses MyBatis.

In fact, it is very simple to implement this. First think about a question:

In a high-concurrency scenario, everything about the database What optimization methods are there?

The following implementation methods are commonly used: read-write separation, caching, master-slave architecture cluster, sub-database and sub-table, etc.

In Internet applications, most of the scenarios involve more reading and less writing. Two libraries are set up, the main library and the reading library.

The main library is responsible for writing, and the slave library is mainly responsible for reading. A reading library cluster can be established to reduce read and write conflicts and relieve database load by isolating the read and write functions on the data source. , the purpose of protecting the database. In actual use, any part involving writing is directly switched to the main library, and the reading part is directly switched to the reading library. This is a typical read-write separation technology.

This article will focus on the separation of reading and writing and explore how to achieve it.

Spring Boot implements MySQL read-write separation technology

Limitations of master-slave synchronization: This is divided into master database and slave database. The master database and slave database maintain the same database structure. The master database Responsible for writing. When writing data, the data will be automatically synchronized to the slave database. The slave database is responsible for reading. When a read request comes, the data is read directly from the reading database, and the master database will automatically copy the data to the slave database. However, this blog does not introduce this part of the configuration knowledge, because it is more focused on operation and maintenance work.

There is a problem involved here:

The delay problem of master-slave replication. When writing to the main database, a read request suddenly comes, and the data is still there. Without complete synchronization, there will be situations where the read requested data cannot be read or the data read is less than the original value. The simplest specific solution is to temporarily point the read request to the main library, but at the same time it also loses part of the meaning of master-slave separation. That is to say, in the strict sense of data consistency scenarios, read-write separation is not completely suitable. Pay attention to the timeliness of updates as a shortcoming of the use of read-write separation.

Okay, this part is just for understanding. Next, let’s look at how to achieve read and write separation through Java code:

Note: This project needs to introduce the following dependencies: Spring Boot, spring-aop, spring-jdbc, aspectjweaver, etc.

Program Yuan: Only 30 days, what should I do? Prepare?

1: Configuration of master-slave data source

We need to configure the master-slave database, master-slave Database configuration is generally written in the configuration file. Through the @ConfigurationProperties annotation, the properties in the configuration file (generally named: application.Properties) can be mapped to specific class properties, so that the written values ??can be read and injected into the specific code configuration. , in accordance with the principle that custom is greater than agreement, we all mark the main library as master and the slave library as slave.

This project uses Alibaba's druid database connection pool and uses the build builder mode to create DataSource objects. DataSource is the data source abstracted at the code level. Then you need to configure sessionFactory, sqlTemplate, transaction manager, etc.

/**
 * 主從配置 
 */
@Configuration
@MapperScan(basePackages = "com.wyq.mysqlreadwriteseparate.mapper", sqlSessionTemplateRef = "sqlTemplate")
public class DataSourceConfig {

    /**
     * 主庫
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.master")
    public DataSource master() {
        return DruidDataSourceBuilder.create().build();
    }

    /**
     * 從庫
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.slave")
    public DataSource slaver() {
        return DruidDataSourceBuilder.create().build();
    }


    /**
     * 實(shí)例化數(shù)據(jù)源路由
     */
    @Bean
    public DataSourceRouter dynamicDB(@Qualifier("master") DataSource masterDataSource,
                                      @Autowired(required = false) @Qualifier("slaver") DataSource slaveDataSource) {
        DataSourceRouter dynamicDataSource = new DataSourceRouter();
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DataSourceEnum.MASTER.getDataSourceName(), masterDataSource);
        if (slaveDataSource != null) {
            targetDataSources.put(DataSourceEnum.SLAVE.getDataSourceName(), slaveDataSource);
        }
        dynamicDataSource.setTargetDataSources(targetDataSources);
        dynamicDataSource.setDefaultTargetDataSource(masterDataSource);
        return dynamicDataSource;
    }


    /**
     * 配置sessionFactory
     * @param dynamicDataSource
     * @return
     * @throws Exception
     */
    @Bean
    public SqlSessionFactory sessionFactory(@Qualifier("dynamicDB") DataSource dynamicDataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setMapperLocations(
                new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/*Mapper.xml"));
        bean.setDataSource(dynamicDataSource);
        return bean.getObject();
    }


    /**
     * 創(chuàng)建sqlTemplate
     * @param sqlSessionFactory
     * @return
     */
    @Bean
    public SqlSessionTemplate sqlTemplate(@Qualifier("sessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }


    /**
     * 事務(wù)配置
     *
     * @param dynamicDataSource
     * @return
     */
    @Bean(name = "dataSourceTx")
    public DataSourceTransactionManager dataSourceTransactionManager(@Qualifier("dynamicDB") DataSource dynamicDataSource) {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dynamicDataSource);
        return dataSourceTransactionManager;
    }
}

2: Configuration of data source routing

Routing is very important in master-slave separation, basically The core of read-write switching. Spring provides AbstractRoutingDataSource to select the current data source according to user-defined rules. Its function is to set the data source used before executing the query, implement dynamic routing data source, and execute it before each database query operation. The abstract method determineCurrentLookupKey() determines which data source to use.

In order to have a global data source manager, we need to introduce the DataSourceContextHolder database context manager, which can be understood as a global variable and can be accessed at any time (see detailed introduction below). Its main function is Save the current data source.

public class DataSourceRouter extends AbstractRoutingDataSource {

    /**
     * 最終的determineCurrentLookupKey返回的是從DataSourceContextHolder中拿到的,因此在動態(tài)切換數(shù)據(jù)源的時(shí)候注解
     * 應(yīng)該給DataSourceContextHolder設(shè)值
     *
     * @return
     */
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.get();

    }
}

三:數(shù)據(jù)源上下文環(huán)境

數(shù)據(jù)源上下文保存器,便于程序中可以隨時(shí)取到當(dāng)前的數(shù)據(jù)源,它主要利用 ThreadLocal 封裝,因?yàn)?ThreadLocal 是線程隔離的,天然具有線程安全的優(yōu)勢。這里暴露了 set 和 get、clear 方法,set 方法用于賦值當(dāng)前的數(shù)據(jù)源名,get 方法用于獲取當(dāng)前的數(shù)據(jù)源名稱,clear 方法用于清除 ThreadLocal 中的內(nèi)容,因?yàn)?ThreadLocal 的 key 是 weakReference 是有內(nèi)存泄漏風(fēng)險(xiǎn)的,通過 remove 方法防止內(nèi)存泄漏。

/**
 * 利用ThreadLocal封裝的保存數(shù)據(jù)源上線的上下文context
 */
public class DataSourceContextHolder {

    private static final ThreadLocal<String> context = new ThreadLocal<>();

    /**
     * 賦值
     *
     * @param datasourceType
     */
    public static void set(String datasourceType) {
        context.set(datasourceType);
    }

    /**
     * 獲取值
     * @return
     */
    public static String get() {
        return context.get();
    }

    public static void clear() {
        context.remove();
    }
}

四:切換注解和 Aop 配置

首先我們來定義一個(gè)@DataSourceSwitcher 注解,擁有兩個(gè)屬性

① 當(dāng)前的數(shù)據(jù)源② 是否清除當(dāng)前的數(shù)據(jù)源,并且只能放在方法上,(不可以放在類上,也沒必要放在類上,因?yàn)槲覀冊谶M(jìn)行數(shù)據(jù)源切換的時(shí)候肯定是方法操作),該注解的主要作用就是進(jìn)行數(shù)據(jù)源的切換,在 dao 層進(jìn)行操作數(shù)據(jù)庫的時(shí)候,可以在方法上注明表示的是當(dāng)前使用哪個(gè)數(shù)據(jù)源。

@DataSourceSwitcher 注解的定義:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface DataSourceSwitcher {
    /**
     * 默認(rèn)數(shù)據(jù)源
     * @return
     */
    DataSourceEnum value() default DataSourceEnum.MASTER;
    /**
     * 清除
     * @return
     */
    boolean clear() default true;

}

DataSourceAop配置:

為了賦予@DataSourceSwitcher 注解能夠切換數(shù)據(jù)源的能力,我們需要使用 AOP,然后使用@Aroud 注解找到方法上有@DataSourceSwitcher.class 的方法,然后取注解上配置的數(shù)據(jù)源的值,設(shè)置到 DataSourceContextHolder 中,就實(shí)現(xiàn)了將當(dāng)前方法上配置的數(shù)據(jù)源注入到全局作用域當(dāng)中。

@Slf4j
@Aspect
@Order(value = 1)
@Component
public class DataSourceContextAop {

    @Around("@annotation(com.wyq.mysqlreadwriteseparate.annotation.DataSourceSwitcher)")
    public Object setDynamicDataSource(ProceedingJoinPoint pjp) throws Throwable {
        boolean clear = false;
        try {
            Method method = this.getMethod(pjp);
            DataSourceSwitcher dataSourceSwitcher = method.getAnnotation(DataSourceSwitcher.class);
            clear = dataSourceSwitcher.clear();
            DataSourceContextHolder.set(dataSourceSwitcher.value().getDataSourceName());
            log.info("數(shù)據(jù)源切換至:{}", dataSourceSwitcher.value().getDataSourceName());
            return pjp.proceed();
        } finally {
            if (clear) {
                DataSourceContextHolder.clear();
            }

        }
    }

    private Method getMethod(JoinPoint pjp) {
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        return signature.getMethod();
    }

}

五:用法以及測試

在配置好了讀寫分離之后,就可以在代碼中使用了,一般而言我們使用在 service 層或者 dao 層,在需要查詢的方法上添加@DataSourceSwitcher(DataSourceEnum.SLAVE),它表示該方法下所有的操作都走的是讀庫。在需要 update 或者 insert 的時(shí)候使用@DataSourceSwitcher(DataSourceEnum.MASTER)表示接下來將會走寫庫。

其實(shí)還有一種更為自動的寫法,可以根據(jù)方法的前綴來配置 AOP 自動切換數(shù)據(jù)源,比如 update、insert、fresh 等前綴的方法名一律自動設(shè)置為寫庫。select、get、query 等前綴的方法名一律配置為讀庫,這是一種更為自動的配置寫法。缺點(diǎn)就是方法名需要按照 aop 配置的嚴(yán)格來定義,否則就會失效。

@Service
public class OrderService {

    @Resource
    private OrderMapper orderMapper;


    /**
     * 讀操作
     *
     * @param orderId
     * @return
     */
    @DataSourceSwitcher(DataSourceEnum.SLAVE)
    public List<Order> getOrder(String orderId) {
        return orderMapper.listOrders(orderId);

    }

    /**
     * 寫操作
     *
     * @param orderId
     * @return
     */
    @DataSourceSwitcher(DataSourceEnum.MASTER)
    public List<Order> insertOrder(Long orderId) {
        Order order = new Order();
        order.setOrderId(orderId);
        return orderMapper.saveOrder(order);
    }
}

六:總結(jié)

還是畫張圖來簡單總結(jié)一下:

Spring Boot implements MySQL read-write separation technology

This article introduces how to achieve database read-write separation. Note that the core point of read-write separation is data routing. You need to inherit AbstractRoutingDataSource and overwrite its determineCurrentLookupKey. ()method. At the same time, you need to pay attention to the global context manager DataSourceContextHolder, which is the main class that saves the data source context and is also the data source value found in the routing method. It is equivalent to a transfer station for data sources, and combined with the bottom layer of jdbc-Template to create and manage data sources, transactions, etc., our database read-write separation is perfectly realized.

The above is the detailed content of Spring Boot implements MySQL read-write separation technology. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undress AI Tool

Undress AI Tool

Undress images for free

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Hot Topics

PHP Tutorial
1488
72
How to use PHP to develop a Q&A community platform Detailed explanation of PHP interactive community monetization model How to use PHP to develop a Q&A community platform Detailed explanation of PHP interactive community monetization model Jul 23, 2025 pm 07:21 PM

1. The first choice for the Laravel MySQL Vue/React combination in the PHP development question and answer community is the first choice for Laravel MySQL Vue/React combination, due to its maturity in the ecosystem and high development efficiency; 2. High performance requires dependence on cache (Redis), database optimization, CDN and asynchronous queues; 3. Security must be done with input filtering, CSRF protection, HTTPS, password encryption and permission control; 4. Money optional advertising, member subscription, rewards, commissions, knowledge payment and other models, the core is to match community tone and user needs.

Automating MySQL Deployments with Infrastructure as Code Automating MySQL Deployments with Infrastructure as Code Jul 20, 2025 am 01:49 AM

To achieve MySQL deployment automation, the key is to use Terraform to define resources, Ansible management configuration, Git for version control, and strengthen security and permission management. 1. Use Terraform to define MySQL instances, such as the version, type, access control and other resource attributes of AWSRDS; 2. Use AnsiblePlaybook to realize detailed configurations such as database user creation, permission settings, etc.; 3. All configuration files are included in Git management, support change tracking and collaborative development; 4. Avoid hard-coded sensitive information, use Vault or AnsibleVault to manage passwords, and set access control and minimum permission principles.

How to set environment variables in PHP environment Description of adding PHP running environment variables How to set environment variables in PHP environment Description of adding PHP running environment variables Jul 25, 2025 pm 08:33 PM

There are three main ways to set environment variables in PHP: 1. Global configuration through php.ini; 2. Passed through a web server (such as SetEnv of Apache or fastcgi_param of Nginx); 3. Use putenv() function in PHP scripts. Among them, php.ini is suitable for global and infrequently changing configurations, web server configuration is suitable for scenarios that need to be isolated, and putenv() is suitable for temporary variables. Persistence policies include configuration files (such as php.ini or web server configuration), .env files are loaded with dotenv library, and dynamic injection of variables in CI/CD processes. Security management sensitive information should be avoided hard-coded, and it is recommended to use.en

How to use PHP to develop product recommendation module PHP recommendation algorithm and user behavior analysis How to use PHP to develop product recommendation module PHP recommendation algorithm and user behavior analysis Jul 23, 2025 pm 07:00 PM

To collect user behavior data, you need to record browsing, search, purchase and other information into the database through PHP, and clean and analyze it to explore interest preferences; 2. The selection of recommendation algorithms should be determined based on data characteristics: based on content, collaborative filtering, rules or mixed recommendations; 3. Collaborative filtering can be implemented in PHP to calculate user cosine similarity, select K nearest neighbors, weighted prediction scores and recommend high-scoring products; 4. Performance evaluation uses accuracy, recall, F1 value and CTR, conversion rate and verify the effect through A/B tests; 5. Cold start problems can be alleviated through product attributes, user registration information, popular recommendations and expert evaluations; 6. Performance optimization methods include cached recommendation results, asynchronous processing, distributed computing and SQL query optimization, thereby improving recommendation efficiency and user experience.

mysql revoke privileges from user mysql revoke privileges from user Jul 16, 2025 am 03:56 AM

To recycle MySQL user permissions using REVOKE, you need to specify the permission type, database, and user by format. 1. Use REVOKEALLPRIVILEGES, GRANTOPTIONFROM'username'@'hostname'; 2. Use REVOKEALLPRIVILEGESONmydb.FROM'username'@'hostname'; 3. Use REVOKEALLPRIVILEGESONmydb.FROM'username'@'hostname'; 3. Use REVOKE permission type ON.*FROM'username'@'hostname'; Note that after execution, it is recommended to refresh the permissions. The scope of the permissions must be consistent with the authorization time, and non-existent permissions cannot be recycled.

Securing MySQL Connections with SSL/TLS Encryption Securing MySQL Connections with SSL/TLS Encryption Jul 21, 2025 am 02:08 AM

Why do I need SSL/TLS encryption MySQL connection? Because unencrypted connections may cause sensitive data to be intercepted, enabling SSL/TLS can prevent man-in-the-middle attacks and meet compliance requirements; 2. How to configure SSL/TLS for MySQL? You need to generate a certificate and a private key, modify the configuration file to specify the ssl-ca, ssl-cert and ssl-key paths and restart the service; 3. How to force SSL when the client connects? Implemented by specifying REQUIRESSL or REQUIREX509 when creating a user; 4. Details that are easily overlooked in SSL configuration include certificate path permissions, certificate expiration issues, and client configuration requirements.

How to build an online customer service robot with PHP. PHP intelligent customer service implementation technology How to build an online customer service robot with PHP. PHP intelligent customer service implementation technology Jul 25, 2025 pm 06:57 PM

PHP plays the role of connector and brain center in intelligent customer service, responsible for connecting front-end input, database storage and external AI services; 2. When implementing it, it is necessary to build a multi-layer architecture: the front-end receives user messages, the PHP back-end preprocesses and routes requests, first matches the local knowledge base, and misses, call external AI services such as OpenAI or Dialogflow to obtain intelligent reply; 3. Session management is written to MySQL and other databases by PHP to ensure context continuity; 4. Integrated AI services need to use Guzzle to send HTTP requests, safely store APIKeys, and do a good job of error handling and response analysis; 5. Database design must include sessions, messages, knowledge bases, and user tables, reasonably build indexes, ensure security and performance, and support robot memory

How to develop AI intelligent form system with PHP PHP intelligent form design and analysis How to develop AI intelligent form system with PHP PHP intelligent form design and analysis Jul 25, 2025 pm 05:54 PM

When choosing a suitable PHP framework, you need to consider comprehensively according to project needs: Laravel is suitable for rapid development and provides EloquentORM and Blade template engines, which are convenient for database operation and dynamic form rendering; Symfony is more flexible and suitable for complex systems; CodeIgniter is lightweight and suitable for simple applications with high performance requirements. 2. To ensure the accuracy of AI models, we need to start with high-quality data training, reasonable selection of evaluation indicators (such as accuracy, recall, F1 value), regular performance evaluation and model tuning, and ensure code quality through unit testing and integration testing, while continuously monitoring the input data to prevent data drift. 3. Many measures are required to protect user privacy: encrypt and store sensitive data (such as AES

See all articles