Solución para procesar datos de tipo Decimal128 en Amazon DocumentDB

un problema matematico sencillo

Antes de comenzar el contenido de hoy, calculemos un problema matemático simple. 0,1 X 0,2 = ? Creo que mucha gente se rió, 0.02, esta es una respuesta que un niño puede responder. Preguntémosle a la computadora este problema matemático y veamos cuál es el resultado.

La comunidad de desarrolladores de tecnología en la nube de Amazon proporciona a los desarrolladores recursos de tecnología de desarrollo global. Hay documentos técnicos, casos de desarrollo, columnas técnicas, videos de capacitación, actividades y concursos, etc. Ayude a los desarrolladores chinos a conectarse con las tecnologías, ideas y proyectos más vanguardistas del mundo, y recomiende desarrolladores o tecnologías chinos sobresalientes a la comunidad global de la nube. Si aún no ha prestado atención / favorito, no se apresure cuando vea esto, ¡ haga clic aquí para convertirlo en su tesoro técnico!

Bienvenido al primer jugador Java

Java Code:
class Main {
 public static void main(String[] args) {
   System.out.println(0.1 * 0.2);
 }
}

La computadora dio la respuesta:

0.020000000000000004

¿Qué tal si te empiezan a sudar las palmas de las manos? Damos la bienvenida al segundo concursante, Node.Js:

Node.Js Code:
> 0.1
0.1

> 0.2
0.2
> 0.1 * 0.2
0.020000000000000004

Todavía 0.020000000000000004. ¿Será que la multiplicación no funciona? ¡Luego cambiamos a la suma y la resta!

El último jugador, Golang, está invitado a entrar:

Golang Code:
a := 1024.1
b := a * 100
fmt.Println(b)

102409.99999999999

c := 2.6
fmt.Println(a - c)

1021.4999999999999

¿Es este un problema de Java o Golang? ¿Te hace sentir que tu visión del mundo se ha puesto patas arriba a medida que seguimos obteniendo los mismos resultados con lenguajes convencionales como Python, Ruby, etc.?

No lo dudes, es la computadora la que está mal. ¿Por qué un CPU tan potente como Intel/AMD/Graviton no puede dar la respuesta correcta a un problema matemático tan simple?

Veamos la verdadera razón. De hecho, se debe a que en el sistema matemático decimal, el tipo de punto flotante binario no es adecuado para expresar o describir los datos en sí. Por ejemplo, el número 0.1, si se describe con un tipo de punto flotante binario, se expresará como 0.0001100110011001101, lo que conduce a la pérdida de precisión o desviación de resultados en muchos valores numéricos.

Por supuesto, esto no causa demasiado problema en nuestra vida diaria. Por ejemplo, los indicadores de temperatura y humedad en el pronóstico del tiempo solo se usan como referencia para la sensación corporal. 35,79999992 grados centígrados no te harán sentir más frío que 36 grados centígrados ni más caliente que 35,5 grados centígrados; cuando estés comprando en el supermercado, el cajero no será muy necesario pagar 12,133333 yuanes, que es 0,133333 yuanes más que 12 yuanes, pero en algunos escenarios de cálculo de alta precisión, la pérdida de precisión numérica tendrá resultados graves o incluso completamente opuestos al resultado final. Entonces, ¿cómo debemos calcular el valor numérico bajo la premisa de conservar la precisión numérica?

Formato de datos decimales

A diferencia de nuestros comunes Float, Double y otros tipos de datos aproximados, Decimal guarda el valor original exacto. Se puede decir que Decimal está especialmente diseñado para el sistema matemático decimal, lo que compensa las deficiencias de la representación binaria de los decimales. Usamos un diagrama esquemático para comprender el principio del decimal.

imagen.png

Decimal en MongoDB

Como base de datos de documentos ampliamente utilizada, MongoDB también sufre problemas de precisión numérica. Para poder almacenar y restaurar valores de alta precisión, nació decimal128, que puede brindar soporte técnico en la escena de guardar valores extremadamente pequeños.

Amazon Cloud Technology ha lanzado Amazon DocumentDB, una base de datos de documentos nativa de la nube compatible con MongoDB. Basándose en la arquitectura de separación de la informática y el almacenamiento, ha ayudado a los clientes a lograr una rápida expansión del clúster, copia de seguridad de transmisión automática y escalado de la capa informática en muchos diferentes escenarios., expansión automática de la capa de almacenamiento y muchas otras funciones de base de datos nativas de la nube, simplificando el trabajo de operación y mantenimiento de la base de datos y mejorando la eficiencia del trabajo. Sin embargo, a partir de julio de 2022, DocumentDB no admite datos en formato Decimal 128. ¿Cómo solucionar este problema?

Mirando la esencia a través del fenómeno, todos son "String"

Los números y los decimales también son un tipo de caracteres, por lo que Decimal en sí también es una extensión basada en el formato de los caracteres. Cuál es la diferencia esencial entre Decimal128 (14.999999) y Decimal ('14.999999') se deja a los amigos técnicos para que piensen. A continuación, utilizamos una solución para resolver el problema de compatibilidad entre DocumentDB y Decimal128. ¡Vamos a unirnos todos!

Esta solución describe los pasos para convertir el formato de datos Decimal128 a String después de un breve tiempo de inactividad, lo que resuelve el problema de conversión de formato de los datos de stock y realiza la migración fuera de línea de MongoDB a DocumentDB a través del Servicio de migración de datos de Amazon.

Code 部分:
##MongoShell Statement,于 MongoDB 执行
##切换至 poc 数据库
use poc;

##创建 origin 数据表并插入两条测试数据,value 字段为 Decimal128
db.origin.insertMany( [
{"_id": 1,  "item": "Byte", "value": Decimal128("1.333333") },

{ "_id": 2, "item": "Bit", "value": Decimal128("2.666666")  }
] )

##结果返回为插入成功
{ acknowledged: true, insertedIds: { '0': 1, '1': 2 } }

##验证一下数据是否存在
db.origin.find();
##返回结果确认数据创建成功;
[
  { _id: 1, item: 'Byte', value: Decimal128("1.333333") },
  { _id: 2, item: 'Bit', value: Decimal128("2.666666") }
]

##转换开始,将 value 字段的 Decimal128格式转换为字符串 String 并另存新字段/列,取名为 newvalue,并将聚合之后的新表输出保存为 poc 数据库下以 newtable 为名的新表

db.getSiblingDB("poc").origin.aggregate( [
{
$addFields: {
newvalue: { $toString: "$value" }
}
},
{ $out : "newtable" }
] )

##确认一下输出是否成功,在看到原始表 origin 之外,增加了一张新表 newtable
show tables;

##得到结果
newtable
origin

##查看一下转换之后新表 newtabl e里面的数据
db.newtable.find();

##结果返回可以看出除了原始表 origin 里的_id,item,value 三个字段之外,新增了一个字段 newvalue,其值与原始 decimal128格式的 value 字段,数值相等,且为字符串 String

[
  {
    _id: 1,
    item: 'Byte',
    value: Decimal128("1.333333"),
    newvalue: '1.333333'
  },
  {
    _id: 2,
    item: 'Bit',
    value: Decimal128("2.666666"),
    newvalue: '2.666666'
  }
]

#经过比对后,数据无误,我们删除原始 decimal128格式的 value 字段
db.newtable.updateMany(
{ "_id": { $gt: 0 } },

{ $unset: { value : "" } 
}
)

##并将 string 格式的 newvalue 重命名为 value
db.newtable.updateMany(
{ "_id": { $gt: 0 } },

{ $rename: { "newvalue": "value"}
 }
)

##返回两条数据修改完成,本段代码为控制台返回,无需执行
{
  acknowledged: true,
  insertedId: null,
  matchedCount: 2,
  modifiedCount: 2,
  upsertedCount: 0
}

##我们确认一下数据
db.newtable.find();

##返回数据中 value 字段已经是 string 格式,本段代码为控制台返回,无需执行
[
  { _id: 1, item: 'Byte', value: '1.333333' },
  { _id: 2, item: 'Bit', value: '2.666666' }
]
##使用 Mongo Shell 原生客户端登录 Amazon DocumentDB
##Bash Statement,其中 YOUR_DOCUMENTDB_ENDPOINT 请使用您环境的##DocumentDB 终端节点地址替换,YOUR_USER_NAME 请使用您环境的 DocumentDB 用户##替换,本操作使用了 DocumentDB 自定义参数组并关闭了 TLS,在您生产环境,建议保留##TLS 处于启用状态
mongosh --host YOUR_DOCUMENTDB_ENDPOINT -u YOUR_USER_NAME -p

##输入用户密码登陆
Enter password: *************

##DocumentDB Statement
##切换至 poc 数据库
Use poc;

##查看数据表
show tables;

##返回为空,当前我们的数据库中没有数据表存在;

Migración de MongoDB a DocumentDB

Además de usar mongodump/mongorestore nativo de MongoDB para la migración de datos, también podemos usar Amazon Data Migration Service (DMS) para usar MongoDB como fuente de datos y Amazon DocumentDB como destino de datos para la migración de datos. Este ejemplo usa este último

1. Busque el servicio DMS a través de la consola y haga clic para ingresar a la consola DMS

imagen.png

2. Haga clic en [Grupo de subred] en la barra de menú izquierda y luego haga clic en [Crear grupo de subred] en la esquina superior derecha

imagen.png

3. Cree un grupo de subred personalizado. Si su entorno se encuentra entre MongoDB y DocumentDB, y hay un entorno de red privada creado por una línea dedicada o VPN, puede crear un grupo de subred personalizado en la subred privada como se muestra en la figura; de lo contrario, cree un grupo de subred personalizado en la pública subred Un grupo de subred personalizado para .

imagen.png

4. Haga clic en [Crear grupo de subred] para completar la creación de la subred.

5. Cree una instancia de replicación

imagen.png

imagen.png

  1. Si su entorno se encuentra entre MongoDB y DocumentDB, y hay un entorno de red privada creado por una línea dedicada o VPN, puede anular la selección de la función [Acceso público] como se muestra en la figura; de lo contrario, marque la función [Acceso público].

imagen.png

7. Crea un punto final

imagen.png

7.1 Cree un punto final de origen con MongoDB como motor

imagen.png

7.2 Reemplace el contenido en el cuadro rojo según su situación real

imagen.png

7.3 Crear un punto final de destino dirigido a Amazon DocumentDB

imagen.png

imagen.png

7.4 Use Secret Manager para administrar la información de la cuenta de DocumentDB (opcional)

Para más detalles, puede leer otro blog especial, haga clic aquí

  1. Crear tareas de migración

imagen.png

8.1 Cree una tarea de migración utilizando el nodo de replicación, el punto final de origen y el punto final de destino que creamos anteriormente

imagen.png

8.2 En la sección de imagen de la tabla, creamos una regla de selección para seleccionar la nueva tabla de datos de la tabla en la base de datos poc y luego hacemos clic para crear una tarea.

imagen.png

8.3 Espere a que se cargue la tarea de migración y el progreso llegue al 100%

imagen.png

Hasta ahora, los datos de stock se han migrado a DocumentDB a través de esta solución combinada con DMS, y se ha completado la conversión de Decimal128 a formato de datos de cadena. Hagamos una verificación.

##登陆到 DocumentDB
##DocumentDB Statement
mongosh --host YOUR_DOCUMENTDB_ENDPOINT -u YOUR_USER_NAME -p

##输入用户密码登陆
Enter password: *************

##切换至 poc 数据库
use poc;

##查看数据表
show tables;

##数据表已经由 DMS 同步到了 DocumentDB
newtable

##验证一下数据
db.newtable.find();

##结果返回符合我们预期
[
  { _id: 1, item: 'Byte', value: '1.333333' },
  { _id: 2, item: 'Bit', value: '2.666666' }
]

Convertir Decimal128 a Java BigDecimal

A través de la solución anterior, hemos convertido correctamente Decimal128 en String y lo hemos almacenado en la base de datos, logrando la preservación de la precisión, pero el valor guardado en formato de cadena no puede participar en el cálculo. ¿Cómo debemos resolver este problema?

En el lenguaje Java, Decimal128 no se puede usar directamente y debe diseñarse especialmente para BigDecimal antes de realizar varios procesamientos y cálculos. Sabemos que Decimal128 es una extensión basada en String, entonces, ¿se puede procesar String de esta manera?

La respuesta es sí, podemos satisfacer nuestras necesidades con la ayuda de una clase pública BigDecimal en Java. El siguiente es un código de muestra de Java, que muestra cómo podemos usar esta clase pública para realizar una conversión bidireccional de formatos, como referencia.

##Java Code
##Transfer String to Java BigDecimal
##引用 BigDecimal 公共类
Import java.math.BigDecimal;
##定义公共类 String2BD
Public class String2BD{
	public static void main(String[ ] args){
	String inputstring = “12.3456”;
	BigDecimal bd = new BigDecimal(inputstring);
	System.out.printIn(bd);
}
}

Convierta la cadena de entrada "12.3456" al número 12.3456, que se puede usar para leer datos en formato de cadena de la base de datos y convertirlos al formato BigDecimal de Java.

##Java Code
##Transfer Java BigDecimal to String
##引用 BigDecimal 公共类
Import java.math.BigDecimal;
##定义公共类 BD2String
Public class BD2String{
	BigDecimal inputbd = new BigDecimal(65.4321)
	String outputstring = inputbd.toString();
	System.out.println(outputstring);
}

Convierta el formato BigDecimal 65.4321 para obtener la cadena "65.4321" y guarde el resultado en la base de datos en formato de cadena.

Resumir

Esta solución utiliza String en lugar de Decimal 128 para completar la migración de datos de stock. Para datos nuevos, con la premisa de garantizar la eficiencia, la conversión bidireccional entre String y BigDecimal se realiza a través de la clase pública BigDecimal de Java, que resuelve la necesidad de usar Decimal128. formato en la demanda de DocumentDB. Las nuevas funciones de DocumentDB se lanzan continuamente, así que permanezca atento.

Link de referencia:

1. Entender rápidamente el decimal

¿Qué es un decimal? Definición, Propiedades, Tipos, Ejemplos, Hechos

2. Use Secret Manager para administrar puntos finales de DMS

Administre sus credenciales de punto de enlace de AWS DMS con Amazon Secrets Manager | Blog de la base de datos de Amazon

3. Clase pública Java BigDecimal de Oracle

BigDecimal (Plataforma Java SE 8)

El autor de este artículo

imagen.png

Fu Xiaoming

Arquitecto de soluciones en la nube de Amazon, responsable de consultoría y diseño arquitectónico de soluciones de computación en la nube, y también comprometido con la investigación y promoción de bases de datos y computación de borde. Antes de unirse a Amazon Cloud Technology, fue responsable del diseño de la arquitectura de corretaje de Internet en el departamento de TI de la industria financiera, y tiene una amplia experiencia en distribución, alta concurrencia y middleware.

Fuente del artículo: https://dev.amazoncloud.cn/column/article/6309d3e2d4155422a4610a4d?sc_medium=regulartraffic&sc_campaign=crossplatform&sc_channel=CSDN 

Supongo que te gusta

Origin blog.csdn.net/u012365585/article/details/132031433
Recomendado
Clasificación