Sharding-JDBC (detallado 1/6)


Contenido: Sharding-JDBC desde el principio hasta el dominio

tema dirección de enlace
Preparación 1: instalar un clúster de máquinas virtuales en la ventana Producción de entorno Linux de máquina virtual distribuida GO
Preparación 2: hay mysql en cada nodo de la máquina virtual Notas de mysql de Centos (incluida la duplicación de mysql vagabunda) GO
Subbase de datos y subtabla-Sharding-JDBC- desde el nivel inicial hasta el nivel 1 Subbase de datos Sharding-JDBC, subtabla (introducción al combate real) GO
Subbase de datos y subtabla-Sharding-JDBC- desde el nivel inicial hasta el nivel 2 Conocimientos básicos de Sharding-JDBC GO
Sharding-JDBC de la entrada al maestro 3 Clave primaria personalizada, clave primaria de copo de nieve distribuida, principio y combate real GO
Sub-base de datos y tabla-Sharding-JDBC- desde la entrada al maestro 4 Réplica maestro-esclavo del clúster MYSQL , principio y combate real GO
Sharding-JDBC desde el nivel inicial hasta el nivel de suficiencia 5 Leer y escribir separación combate real GO
Sharding-JDBC desde el nivel inicial hasta el nivel de suficiencia 6 Principio de implementación de Sharding-JDBC GO
Código fuente para Sharding-JDBC desde la entrada hasta el maestro dirección del almacén de git IR

1. Acerca de Sharding-JDBC

No diré más sobre la introducción de Sharding-JDBC. Sharding-JDBC fue un marco de expansión horizontal para bases de datos relacionales desarrollado por Dangdang.com. Ahora se ha donado a Apache. Para conocer su principio, consulte el siguiente blog.

La dirección del documento de shardingsphere es: https://shardingsphere.apache.org/document/current/cn/overview/.

2 Escenario de combate real de Sharding-JDBC

Antes de obtener una comprensión más profunda, obtengamos una experiencia práctica para aumentar la impresión y despertar el interés.

En circunstancias normales, todo el mundo utilizará la tabla y la biblioteca de segmentación horizontal: una tabla se divide horizontalmente en varias tablas y también se puede colocar en varias bibliotecas . Esto involucra las reglas de fragmentación de datos, las más comunes son: tabla de módulo hash, tabla de rango numérico y tabla de algoritmo hash consistente.

1. Tabla de módulo de hash

El concepto generalmente adopta el método de segmentación de Hash modulo, por ejemplo: supongamos que 4 tablas se dividen en goods_id. (Goods_id% 4 tabla de determinación de redondeo)

img

ventaja

  • La fragmentación de datos es relativamente uniforme y no es propensa a puntos calientes y cuellos de botella de acceso concurrente.

Desventaja

  • Cuando el clúster fragmentado se expande más tarde, es difícil migrar datos antiguos.

  • Es fácil afrontar el complejo problema de las consultas entre fragmentos. Por ejemplo, en el ejemplo anterior, si las condiciones de consulta utilizadas con frecuencia no incluyen Goods_id, la base de datos no se podrá ubicar. Por lo tanto, es necesario iniciar una consulta en 4 bases de datos al mismo tiempo
    y luego fusionar las datos en la memoria, tome el conjunto más pequeño y devuélvalo a la aplicación.

2. Subtabla de rango numérico

El concepto se divide en intervalos de tiempo o intervalos de identificación. Por ejemplo: asigne los registros con Goods_id 11000 a la primera tabla, asigne los registros con 10012000 a la segunda tabla, y así sucesivamente.

img

ventaja

  • Tamaño de mesa única controlable
  • Naturalmente, es fácil expandir horizontalmente. Si desea expandir todo el clúster de fragmentos más adelante, solo necesita agregar nodos y no es necesario migrar los datos de otros fragmentos.
  • Cuando se utilizan campos de fragmentos para la búsqueda de rango, los fragmentos continuos pueden localizar fragmentos rápidamente para realizar consultas rápidas, lo que evita eficazmente el problema de la consulta entre fragmentos.

Desventaja

  • Los datos calientes se convierten en un cuello de botella en el rendimiento.
    Por ejemplo, fragmentación por campo de tiempo. Algunos fragmentos almacenan datos en el período de tiempo más reciente y pueden leerse y escribirse con frecuencia, mientras que los datos históricos almacenados en algunos fragmentos rara vez se consultan.

3. Algoritmo hash consistente

El algoritmo Hash consistente puede resolver el problema de la necesidad de migrar datos antiguos cuando el clúster fragmentado se expande debido al módulo Hash. En cuanto a los principios específicos, no entraré en detalles aquí.

Puede consultar un blog: Algoritmo hash consistente (subbase de datos y subtabla, equilibrio de carga, etc.)

4. Combate real: tabla de puntuación de módulo Hash simple

Suponiendo que user_id y order_id de una tabla de pedidos se distribuyen de manera relativamente uniforme, de acuerdo con el tamaño de los datos de 1000W, la siguiente subbase de datos y estructura de subtabla se pueden utilizar para guardar:

db0
├── t_order0
└── t_order1
db1
├── t_order0
└── t_order1

Simplemente subbase de datos y subtabla: de acuerdo con las reglas de user_id% 2 para la subbase de datos, de acuerdo con las reglas de order_id% 2 para la subtabla

3 El diseño de la estructura de la mesa de la biblioteca:

3.1 Tabla de orden lógico

La estructura de la tabla de orden lógico es la siguiente:

3.2 Biblioteca de pedidos en el nodo 1 (cdh1)

DROP TABLE IF EXISTS `t_order_0`;
DROP TABLE IF EXISTS `t_order_1`;


DROP TABLE IF EXISTS `t_config`;
CREATE TABLE `t_order_0` (`order_id` bigInt NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_1` (`order_id` bigInt NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));

3.3 Biblioteca de pedidos en el nodo 2 (cdh2)

DROP TABLE IF EXISTS `t_order_0`;
DROP TABLE IF EXISTS `t_order_1`;


DROP TABLE IF EXISTS `t_config`;
CREATE TABLE `t_order_0` (`order_id` bigInt NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_1` (`order_id` bigInt NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));

En ambas bases de datos, hay dos tablas t_order_0 y t_order_1

4 Configuración de la subtabla de la subbase de datos Sharding-JDBC

  • Sub-biblioteca

El ejemplo de subbase de datos en este artículo es relativamente simple. Se juzga de acuerdo con el campo user_id% 2 en la tabla de la base de datos. Si user_id% 2 == 0, use ds0, de lo contrario use ds1.

  • Submesa

La submuestra es relativamente simple, juzgue de acuerdo con el campo order_id% 2 en la tabla de la base de datos, si order_id% 2 == 0, use t_order_0, de lo contrario use t_order_1.

La subbase de datos horizontal y la subtabla de la tabla de datos que se muestra en la siguiente figura se realizan en la tabla t_order, como se muestra en la siguiente figura:

(También se requiere una fragmentación horizontal similar para la tabla t_order_item, pero se omite esta parte de la configuración):

En el archivo de configuración yml, puede usar expresiones Groovy para configurar las reglas para la subbase de datos y la tabla. Las expresiones Groovy específicas son las siguientes:

表达式一: 例如 ds0.t_order_0
ds$->{0..1}.t_order_$->{0..1}

表达式一:db 维度的拆分, 例如 ds_0、ds_1
ds_${user_id % 2}

表达式一:table 维度的拆分, 例如 t_order_1
t_order_${order_id % 2}

Estas expresiones se denominan expresiones Groovy y su significado es fácil de reconocer:

1) Dividir t_order en dos dimensiones: dimensión db y dimensión de la tabla;

2) En la dimensión db, los registros de user_id% 2 == 0 caen todos a ds0, y los registros de user_id% 2 == 1 caen todos a ds1; (algunas personas llaman a este proceso sub-base de datos horizontal, de hecho, su esencia sigue siendo horizontal La tabla está dividida, pero la tabla dividida se coloca en dos instancias de base de datos de acuerdo con el user_id en la tabla).

3) En la dimensión de la tabla, todos los registros con order_id% 2 == 0 caen en t_order0, y todos los registros con order_id% 2 == 1 caen en t_order1.

4) La lectura y escritura de registros se realiza en esta dirección, la "dirección" es el método de fragmentación, que es el encaminamiento.

Con esta concisa expresión de Groovy, puede establecer la estrategia de fragmentación y el algoritmo de fragmentación. Pero el significado que se puede expresar de esta manera es limitado. Por lo tanto, el funcionario proporciona una interfaz de estrategia de fragmentación y una interfaz de algoritmo de fragmentación, lo que le permite expresar estrategias de fragmentación y algoritmos de fragmentación más complejos con código Java.

De hecho, el algoritmo de fragmentación es una parte integral de la estrategia de fragmentación, y la configuración de la estrategia de fragmentación = configuración de la clave de fragmentación + configuración del algoritmo de fragmentación. La estrategia utilizada en la configuración anterior es la estrategia de fragmentación de tipo Inline, y el algoritmo utilizado es el algoritmo de expresión de línea de tipo Inline.

La configuración específica es la siguiente:

spring:
  application:
    name: sharding-jdbc-provider
  jpa:  #配置自动建表:updata:没有表新建,有表更新操作,控制台显示建表语句
    hibernate:
      ddl-auto: none
      dialect: org.hibernate.dialect.MySQL5InnoDBDialect
      show-sql: true
  freemarker:
    allow-request-override: false
    allow-session-override: false
    cache: false
    charset: UTF-8
    check-template-location: true
    content-type: text/html
    enabled: true
    expose-request-attributes: false
    expose-session-attributes: false
    expose-spring-macro-helpers: true
    prefer-file-system-access: true
    settings:
      classic_compatible: true
      default_encoding: UTF-8
      template_update_delay: 0
    suffix: .ftl
    template-loader-path: classpath:/templates/
  shardingsphere:
    props:
      sql:
        show: true
    # 配置真实数据源
    datasource:
      common:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        validationQuery: SELECT 1 FROM DUAL
      names: ds0,ds1
      ds0:
          url: jdbc:mysql://cdh1:3306/store?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=true&serverTimezone=UTC
          username: root
          password: 123456
      # 配置第 2 个数据源  org.apache.commons.dbcp2
      ds1:
          url: jdbc:mysql://cdh2:3306/store?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=true&serverTimezone=UTC
          username: root
          password: 123456
    # 配置分片规则和分片算法
    rules:
      # 配置分片规则
      sharding:
        tables:
          # 配置 t_order 表规则
          t_order:
            actualDataNodes: ds$->{0..1}.t_order_$->{0..1}
            # 配置分库策略
            databaseStrategy:
              standard:
                shardingColumn: user_id
                shardingAlgorithmName: database-inline
            # 配置分表策略
            tableStrategy:
              standard:
                shardingColumn: order_id
                shardingAlgorithmName: table-inline
            keyGenerateStrategy:
              column: order_id
              keyGeneratorName: snowflake
        # 配置分片算法
        bindingTables: t_order
        sharding-algorithms:
          database-inline:
            type: INLINE
            props:
              algorithm-expression: ds$->{user_id % 2}
          table-inline:
            type: INLINE
            props:
              algorithm-expression: t_order_$->{order_id % 2}
        keyGenerators:
          snowflake:
            type: SNOWFLAKE
            props:
              workerId: 123

5. Implementación del código

Este artículo utiliza SpringBoot2, SpringData-JPA, grupo de conexiones Druid y sharding-jdbc 5 de Dangdang.

5.1 Archivos dependientes

Cree un nuevo proyecto, agregue la dependencia sharding-jdbc-core de Dangdang y el grupo de conexiones druidas. Ver proyecto de código fuente.

5.2 Inicio

Utilice @EnableTransactionManagement para abrir la transacción,

Use la anotación @EnableConfigurationProperties para agregar la entidad de configuración, ingrese el código completo de la clase de inicio como se muestra.

package com.crazymaker.springcloud.sharding.jdbc.demo.start;
@EnableConfigurationProperties

@SpringBootApplication(scanBasePackages =
        {"com.crazymaker.springcloud.sharding.jdbc.demo",
//                 "com.crazymaker.springcloud.base",
//                 "com.crazymaker.springcloud.standard"
        }, exclude = {
        DataSourceAutoConfiguration.class,
        SecurityAutoConfiguration.class,
        DruidDataSourceAutoConfigure.class})
@EnableScheduling
@EnableSwagger2
@EnableJpaRepositories(basePackages = {
        "com.crazymaker.springcloud.sharding.jdbc.demo.dao.impl",
//        "com.crazymaker.springcloud.base.dao"
})
@EnableTransactionManagement(proxyTargetClass = true)

@EntityScan(basePackages = {
//        "com.crazymaker.springcloud.user.*.dao.po",
        "com.crazymaker.springcloud.sharding.jdbc.demo.entity.jpa",
//        "com.crazymaker.springcloud.standard.*.dao.po"
})
/**
 * 启用 Hystrix
 */
@EnableHystrix
@EnableFeignClients(
        basePackages = "com.crazymaker.springcloud.user.info.remote.client",
        defaultConfiguration = FeignConfiguration.class)
@Slf4j
@EnableEurekaClient
public class ShardingJdbcDemoCloudApplication
{
    public static void main(String[] args)
    {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(ShardingJdbcDemoCloudApplication.class, args);


        Environment env = applicationContext.getEnvironment();
        String port = env.getProperty("server.port");
        String path = env.getProperty("server.servlet.context-path");
        System.out.println("\n----------------------------------------------------------\n\t" +
                "Application is running! Access URLs:\n\t" +
                "Local: \t\thttp://localhost:" + port + path + "/index.html\n\t" +
                "swagger-ui: \thttp://localhost:" + port + path + "/swagger-ui.html\n\t" +
                "----------------------------------------------------------");

    }

}

5.3 Clase de entidad y capa de operación de la base de datos

Es una entidad simple y un repositorio. Para obtener más detalles, consulte el proyecto de código fuente.

/*
 * Copyright 2016-2018 shardingsphere.io.
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * </p>
 */

package com.crazymaker.springcloud.sharding.jdbc.demo.entity.jpa;

import com.crazymaker.springcloud.sharding.jdbc.demo.entity.Order;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "t_order")
public final class OrderEntity extends Order
{
    
    @Id
    @Column(name = "order_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Override
    public long getOrderId() {
        return super.getOrderId();
    }
    
    @Column(name = "user_id")
    @Override
    public int getUserId() {
        return super.getUserId();
    }
    
    @Column(name = "status")
    public String getStatus() {
        return super.getStatus();
    }
}

Inserte la descripción de la imagen aquí

5.4 Capa de servicio

Inserte la descripción de la imagen aquí

Para obtener más detalles, consulte el proyecto de código fuente.

5.4 Controlador

A continuación, cree un controlador para probar. El método de guardar utiliza insertar datos y ver datos. De acuerdo con nuestras reglas, los datos se insertarán en cada biblioteca. Al mismo tiempo, también creé un método de consulta aquí para consultar todos los pedidos.

package com.crazymaker.springcloud.sharding.jdbc.demo.controller;

@RestController
@RequestMapping("/api/sharding/")
@Api(tags = "sharding jdbc 演示")
public class ShardingJdbcController
{

    @Resource
    JpaEntityService jpaEntityService;



    @PostMapping("/order/add/v1")
    @ApiOperation(value = "插入订单")
    public RestOut<Order> orderAdd(@RequestBody Order dto)
    {
        jpaEntityService.addOrder(dto);

        return RestOut.success(dto);
    }



    @PostMapping("/order/list/v1")
    @ApiOperation(value = "查询订单")
    public RestOut<List<Order>> listAll()
    {
        List<Order> list = jpaEntityService.selectAll();

        return RestOut.success(list);
    }


}

6 Realice la prueba

6.1 fanfarronería abierta

Inicie la aplicación.

Luego, visite http: // localhost: 7700 / sharding-jdbc-provider / swagger-ui.html en el navegador o en la herramienta de solicitud HTTP, como se muestra en la figura

Inserte la descripción de la imagen aquí

6.2 Agregar dos datos

Inserte la descripción de la imagen aquí

Use la interfaz para insertar un pedido, puede insertar un pedido, preste atención al ID de usuario% 2 == 0 para ingresar db1, preste atención al ID de usuario% 2 == 1 para ingresar db2, ¿en qué tabla está?

Debido a que el orderid es generado por el algoritmo de copo de nieve, si orderid% 2 == 0, ingrese t_order_0; de lo contrario, use t_order_1.

Después de insertar, puede ver los resultados a través de la base de datos. Los detalles son los siguientes:

Inserte la descripción de la imagen aquí

6.3 Ver datos

Inserte la descripción de la imagen aquí

Utilice el método de consulta del programa, shardingjdbc, para averiguar todos los pedidos.

7 Resumen

Usando shardingjdbc, excepto por algunas reglas especiales para la configuración de la fuente de datos, no hay mucha diferencia entre el programa de capa de persistencia y el código JPA ordinario.

Por supuesto, si desea implementar una lógica de subtabla de subbase de datos especial, aún necesita mover el código, consulte la descomposición posterior.

Volver a ◀ Círculo de creadores de locos

Comunidad de investigación de alta concurrencia de Crazy Maker Circle-Java, abre la puerta a grandes fábricas para todos

Supongo que te gusta

Origin blog.csdn.net/crazymakercircle/article/details/112117407
Recomendado
Clasificación