java分佈式事務處理--最終事務一致性

在大型系統架構時咱們會進行分庫設計,好比用戶庫、訂單庫。若是採用了dubbo會產生服務,若是目前有兩個服務,用戶服務和訂單服務。java

實際業務中,用戶下單支付成功後,並改變用戶的狀態或增長用戶的積分。這樣過程當中就會產生事務問題。這裏咱們採用最終事務一致性。sql

    大體實現思路,把分佈式事務切割成小事務,用消息隊列消除分佈式事務。實現方式以下:session

訂單功能的小事務以下:架構

首先:訂單服務。分佈式

jmsTemplate.setSessionTransacted(true);
		transactionTemplate.execute(new TransactionCallback<String>()
		{

			@Override
			public String doInTransaction(TransactionStatus status)
			{
				// TODO Auto-generated method stub
				Connection connection = null;
				Session session = null;
				try
				{
					String orderId = System.currentTimeMillis() + "";
					String sql = "insert into order (order_id,user_id) values (?,?)";
					jdbcTemplate.update(sql, new Object[]
					{ orderId, userId });
					connection = jmsTemplate.getConnectionFactory().createConnection();
					session = connection.createSession(true, Session.CLIENT_ACKNOWLEDGE);
					Destination destination = session.createQueue("transactionQueue");
					MessageProducer producer = session.createProducer(destination);
					producer.setDeliveryMode(DeliveryMode.PERSISTENT);
					String text = "orderid";
					MapMessage message = session.createMapMessage();//Message(text);
					message.setString("order_id", orderId);
					message.setString("user_id", userId);
					message.setString("status", "1");
					producer.send(message);
					session.commit();
				} catch (Exception ex)
				{
					// TODO: handle exception
					status.setRollbackOnly();
					try
					{
						session.rollback();
					} catch (JMSException e)
					{
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					ex.printStackTrace();
				} finally
				{
					try
					{
						session.close();
					} catch (JMSException e)
					{
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				return null;
			}
		});

 

用戶服務監聽消息隊列ide

public void handlerMessage(final MapMessage mapMessage, final Session session) throws JMSException
	{
		getTransactionTemplate().execute(new TransactionCallback<String>()
		{

			@Override
			public String doInTransaction(TransactionStatus status)
			{
				int result = 0;
				try
				{
					//String status, String user_id, String order_id
					updateUserLevel(mapMessage.getString("status"), 
                                    mapMessage.getString("user_id"),
							        mapMessage.getString("order_id"));
				} catch (Exception e)
				{
					try
					{
						session.rollback();
					} catch (JMSException ex)
					{
						logger.error("JMS事務回滾異常", ex);
						ex.printStackTrace();
					}
					status.setRollbackOnly();

				}

				return String.valueOf(result);

			}
		});

	}

消息隊列配置設計

​
<amq:redeliveryPolicy id="activeMQRedeliveryPolicy" destination="#defaultDestination"  redeliveryDelay="1000" maximumRedeliveries="10" />

​

 

消息隊列重試次數10次,若是一次失敗,能夠多試幾回。code

若是消息隊列最終失敗,則監聽失敗信息,採用事務補償機制,刪除以前增長的訂單或其餘處理。xml

相關文章
相關標籤/搜索