mirror of
https://github.com/Snailclimb/JavaGuide
synced 2025-08-10 00:41:37 +08:00
Compare commits
6 Commits
895bf6ee2a
...
3b02b49925
Author | SHA1 | Date | |
---|---|---|---|
|
3b02b49925 | ||
|
af205e8bb2 | ||
|
60e3c5a05b | ||
|
abf59e9fc2 | ||
|
67597d7682 | ||
|
0cd8299a62 |
@ -1,5 +1,5 @@
|
||||
---
|
||||
title: MySQL时间类型数据存储建议
|
||||
title: MySQL日期类型选择建议
|
||||
category: 数据库
|
||||
tag:
|
||||
- MySQL
|
||||
|
@ -169,9 +169,10 @@ MySQL binlog(binary log 即二进制日志文件) 主要记录了 MySQL 数据
|
||||
|
||||
引入分库分表之后,会给系统带来什么挑战呢?
|
||||
|
||||
- **join 操作**:同一个数据库中的表分布在了不同的数据库中,导致无法使用 join 操作。这样就导致我们需要手动进行数据的封装,比如你在一个数据库中查询到一个数据之后,再根据这个数据去另外一个数据库中找对应的数据。
|
||||
- **事务问题**:同一个数据库中的表分布在了不同的数据库中,如果单个操作涉及到多个数据库,那么数据库自带的事务就无法满足我们的要求了。
|
||||
- **分布式 id**:分库之后, 数据遍布在不同服务器上的数据库,数据库的自增主键已经没办法满足生成的主键唯一了。我们如何为不同的数据节点生成全局唯一主键呢?这个时候,我们就需要为我们的系统引入分布式 id 了。
|
||||
- **join 操作**:同一个数据库中的表分布在了不同的数据库中,导致无法使用 join 操作。这样就导致我们需要手动进行数据的封装,比如你在一个数据库中查询到一个数据之后,再根据这个数据去另外一个数据库中找对应的数据。不过,很多大厂的资深 DBA 都是建议尽量不要使用 join 操作。因为 join 的效率低,并且会对分库分表造成影响。对于需要用到 join 操作的地方,可以采用多次查询业务层进行数据组装的方法。不过,这种方法需要考虑业务上多次查询的事务性的容忍度。
|
||||
- **事务问题**:同一个数据库中的表分布在了不同的数据库中,如果单个操作涉及到多个数据库,那么数据库自带的事务就无法满足我们的要求了。这个时候,我们就需要引入分布式事务了。关于分布式事务常见解决方案总结,网站上也有对应的总结:<https://javaguide.cn/distributed-system/distributed-transaction.html> 。
|
||||
- **分布式 ID**:分库之后, 数据遍布在不同服务器上的数据库,数据库的自增主键已经没办法满足生成的主键唯一了。我们如何为不同的数据节点生成全局唯一主键呢?这个时候,我们就需要为我们的系统引入分布式 ID 了。关于分布式 ID 的详细介绍&实现方案总结,网站上也有对应的总结:<https://javaguide.cn/distributed-system/distributed-id.html> 。
|
||||
- **跨库聚合查询问题**:分库分表会导致常规聚合查询操作,如 group by,order by 等变得异常复杂。这是因为这些操作需要在多个分片上进行数据汇总和排序,而不是在单个数据库上进行。为了实现这些操作,需要编写复杂的业务代码,或者使用中间件来协调分片间的通信和数据传输。这样会增加开发和维护的成本,以及影响查询的性能和可扩展性。
|
||||
- ......
|
||||
|
||||
另外,引入分库分表之后,一般需要 DBA 的参与,同时还需要更多的数据库服务器,这些都属于成本。
|
||||
|
@ -256,7 +256,7 @@ public class BigDecimalUtil {
|
||||
}
|
||||
BigDecimal b1 = BigDecimal.valueOf(v1);
|
||||
BigDecimal b2 = BigDecimal.valueOf(v2);
|
||||
return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue();
|
||||
return b1.divide(b2, scale, RoundingMode.HALF_EVEN).doubleValue();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -351,6 +351,12 @@ public class BigDecimalUtil {
|
||||
}
|
||||
```
|
||||
|
||||
相关 issue:[建议对保留规则设置为 RoundingMode.HALF_EVEN,即四舍六入五成双](https://github.com/Snailclimb/JavaGuide/issues/1122) 。
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
## 总结
|
||||
|
||||
浮点数没有办法用二进制精确表示,因此存在精度丢失的风险。
|
||||
|
@ -153,11 +153,6 @@ icon: "xitongsheji"
|
||||
|
||||
- [Disruptor](https://github.com/LMAX-Exchange/disruptor):Disruptor 是英国外汇交易公司 LMAX 开发的一个高性能队列,研发的初衷是解决内存队列的延迟问题(在性能测试中发现竟然与 I/O 操作处于同样的数量级)。相关阅读:[《高性能内存队列——Disruptor》](https://tech.meituan.com/2016/11/18/disruptor.html) 。
|
||||
|
||||
**可视化管理工具**:
|
||||
|
||||
- [Kafdrop](https://github.com/obsidiandynamics/kafdrop) : 一个用于查看 Kafka 主题和浏览消费者组的 Web UI。
|
||||
- [EFAK](https://github.com/smartloli/EFAK) (Eagle For Apache Kafka,以前叫做 Kafka Eagle):一个简单的高性能监控系统,用于对 Kafka 集群进行全面的监控和管理。
|
||||
|
||||
### 读写分离和分库分表
|
||||
|
||||
- [ShardingSphere](https://github.com/apache/shardingsphere):ShardingSphere 是一套开源的分布式数据库中间件解决方案组成的生态圈,它由 Sharding-JDBC、Sharding-Proxy 和 Sharding-Sidecar(计划中)这 3 款相互独立的产品组成。
|
||||
|
@ -51,3 +51,8 @@ icon: tool
|
||||
|
||||
- [PrettyZoo](https://github.com/vran-dev/PrettyZoo):一个基于 Apache Curator 和 JavaFX 实现的 ZooKeeper 图形化管理客户端,颜值非常高,支持 Mac / Windows / Linux 。你可以使用 PrettyZoo 来实现对 ZooKeeper 的可视化增删改查。
|
||||
- [zktools](https://zktools.readthedocs.io/en/latest/#installing):一个低延迟的 ZooKeeper 图形化管理客户端,颜值非常高,支持 Mac / Windows / Linux 。你可以使用 zktools 来实现对 ZooKeeper 的可视化增删改查。
|
||||
|
||||
## Kafka
|
||||
- [Kafka UI](https://github.com/provectus/kafka-ui):免费的开源 Web UI,用于监控和管理 Apache Kafka 集群。
|
||||
- [Kafdrop](https://github.com/obsidiandynamics/kafdrop) : 一个用于查看 Kafka 主题和浏览消费者组的 Web UI。
|
||||
- [EFAK](https://github.com/smartloli/EFAK) (Eagle For Apache Kafka,以前叫做 Kafka Eagle):一个简单的高性能监控系统,用于对 Kafka 集群进行全面的监控和管理。
|
@ -679,6 +679,25 @@ private void method1() {
|
||||
|
||||
解决办法就是避免同一类中自调用或者使用 AspectJ 取代 Spring AOP 代理。
|
||||
|
||||
[issue #2091](https://github.com/Snailclimb/JavaGuide/issues/2091)补充了一个例子:
|
||||
|
||||
```java
|
||||
@Service
|
||||
public class MyService {
|
||||
|
||||
private void method1() {
|
||||
((MyService)AopContext.currentProxy()).method2(); // 先获取该类的代理对象,然后通过代理对象调用method2。
|
||||
//......
|
||||
}
|
||||
@Transactional
|
||||
public void method2() {
|
||||
//......
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
上面的代码确实可以在自调用的时候开启事务,但是这是因为使用了 `AopContext.currentProxy()` 方法来获取当前类的代理对象,然后通过代理对象调用 `method2()`。这样就相当于从外部调用了 `method2()`,所以事务注解才会生效。我们一般也不会在代码中这么写,所以可以忽略这个特殊的例子。
|
||||
|
||||
#### `@Transactional` 的使用注意事项总结
|
||||
|
||||
- `@Transactional` 注解只有作用到 public 方法上事务才生效,不推荐在接口上使用;
|
||||
|
Loading…
x
Reference in New Issue
Block a user