在實現同城多活的方案中,機房之間的資料同步是一個至關重要的部分。通常,這類系統需要保證跨機房的資料一致性和高可用性。爲了實現這個目標,可以採用資料庫同步、訊息佇列、分散式快取等技術。
實際場景案例
假設我們有一個電商平臺,在同城的兩個資料中心(機房A和機房B)中部署了相同的服務例項。在這些例項中,使用者訂單和庫存資訊需要在兩個機房之間進行實時同步,以保證無論使用者訪問哪個機房,都能獲得最新的訂單和庫存狀態。
方案設計
資料同步方案: 我們可以使用資料庫主從複製來保證資料的一致性。主資料庫部署在機房A中,從資料庫部署在機房B中。同時,透過訊息佇列(如Kafka)將訂單和庫存的變動事件同步到另一個機房。這樣,當訂單資訊或庫存變動時,會透過訊息佇列實時同步到另一機房的服務例項。
服務架構:
服務透過
Spring Boot
來提供REST API。使用
Spring Data JPA
進行資料庫操作。使用
Kafka
作為訊息佇列,監聽訂單變動的事件,並將資料同步到另一個機房。資料一致性保證:
利用資料庫的事務管理來保證資料一致性。
使用Kafka的訊息佇列來非同步處理訂單和庫存的同步操作,確保資料不會丟失。
詳細程式碼實現
1. 環境設定
我們首先需要在Spring Boot中配置資料庫連線和Kafka訊息佇列。假設我們使用MySQL和Kafka來實現資料同步。
1.1 資料庫配置(application.yml
)
spring: datasource: url: jdbc:mysql://localhost:3306/order_db?useUnicode=true&characterEncoding=utf8 username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: ddl-auto: update show-sql: true kafka: bootstrap-servers: localhost:9092 consumer: group-id: order-sync-group producer: acks: all
1.2 Kafka配置類
@Configuration public class KafkaConfig { @Bean public ProducerFactory<String, Order> producerFactory() { Map<String, Object> configProps = new HashMap<>(); configProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092"); configProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class); configProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, JsonSerializer.class); return new DefaultKafkaProducerFactory<>(configProps); } @Bean public KafkaTemplate<String, Order> kafkaTemplate() { return new KafkaTemplate<>(producerFactory()); } @Bean public ConsumerFactory<String, Order> consumerFactory() { Map<String, Object> configProps = new HashMap<>(); configProps.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092"); configProps.put(ConsumerConfig.GROUP_ID_CONFIG, "order-sync-group"); configProps.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, JsonDeserializer.class); return new DefaultKafkaConsumerFactory<>(configProps); } @Bean public ConcurrentMessageListenerContainer<String, Order> messageListenerContainer() { MessageListenerContainer container = new ConcurrentMessageListenerContainer<>( consumerFactory(), new ContainerProperties("order-topic")); container.setupMessageListener(new MessageListener<String, Order>() { @Override public void onMessage(ConsumerRecord<String, Order> record) { Order order = record.value(); // 將訂單同步到本地資料庫 orderService.saveOrder(order); } }); return container; } }
1.3 Order實體類
@Entity public class Order { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String userId; private String productId; private Integer quantity; private Double totalPrice; // Getters and Setters }
1.4 OrderService類(處理業務邏輯)
@Service public class OrderService { @Autowired private OrderRepository orderRepository; @Autowired private KafkaTemplate<String, Order> kafkaTemplate; @Transactional public Order createOrder(Order order) { // 儲存訂單到資料庫 Order savedOrder = orderRepository.save(order); // 將訂單資訊傳送到Kafka佇列 kafkaTemplate.send("order-topic", savedOrder); return savedOrder; } public void saveOrder(Order order) { // 將接收到的訂單同步到本地資料庫 orderRepository.save(order); } }
1.5 OrderController類(提供API介面)
@RestController @RequestMapping("/orders") public class OrderController { @Autowired private OrderService orderService; @PostMapping public ResponseEntity<Order> createOrder(@RequestBody Order order) { Order createdOrder = orderService.createOrder(order); return ResponseEntity.status(HttpStatus.CREATED).body(createdOrder); } }
2. 訂單建立和資料同步
當一個使用者在機房A建立訂單時,OrderService
會將訂單資訊儲存到本地資料庫,並透過Kafka將訂單資訊推送到訊息佇列(order-topic
)。機房B的服務例項會從訊息佇列中獲取訂單資訊,並將訂單同步到本地資料庫。這樣,無論使用者訪問哪個機房,訂單資訊都會保持同步。
3. 資料庫主從同步(可選)
如果你希望資料庫層面也實現主從同步,可以考慮使用MySQL的主從複製或者分散式資料庫系統(如TiDB、PolarDB等)。在此示例中,主資料庫和從資料庫可以分佈在不同的機房,透過資料庫的複製機制保持資料一致性。
4. 高可用設計
爲了提高系統的高可用性,可以使用以下策略:
負載均衡: 在機房A和機房B之間部署負載均衡器(如Nginx、Spring Cloud Gateway等),確保使用者請求可以均勻地分配到兩個機房的服務例項。
服務降級與容錯: 使用
Spring Cloud Circuit Breaker
等技術,在一臺機房的服務不可用時,自動切換到另一臺機房,確保服務的持續可用。定期監控: 對Kafka和資料庫進行定期監控,確保資料同步過程中的問題能夠及時發現並處理。
總結
透過結合SpringBoot框架、MySQL主從複製、Kafka訊息佇列等技術,可以實現機房之間的實時資料同步。在訂單和庫存資訊變更時,透過Kafka非同步傳遞變更資料,並透過資料庫儲存同步資料,確保同城多活架構中的資料一致性和高可用性。