本文以搭建阿里云雙機房數據訪問代理(ODP)實例訪問 OceanBase 為例,介紹如何使用阿里云雙機房下的 ODP。
本文以上海非金區(華東 2)為例,其他地域的操作步驟類似。
示例背景
部署拓撲:應用部署于上海非金可用區 A 與可用區 C,每個可用區的應用承載 50 個分片的流量(依賴流量調撥);同時創建部署于可用區 A 與可用區 C 的 ODP 實例(分別映射到可用區 A 與可用區 C 的交換機),應用連接當前可用區內的 ODP 實例。
數據拓撲:共分 100 個分片,即百庫百表。使用公有云 OceanBase 的單集群雙租戶,每個租戶分配 50 分片。其中,第一個租戶的主可用區設置為可用區 A,分配前 50 分片;第二個可用區的主可用區設置為可用區 C,分配后 50 分片。
前 50 分片的 leader 所在可用區 A 宕機后,OB 會將該 50 分片的 leader 切換至可用區 B
此時,前 50 分片的流量會調撥給 A 可用區內的應用,應用連接當前可用區 A 的 ODP(未產生跨機房),ODP 會連接主可用區在可用區 A 的 OceanBase 租戶,訪問該租戶內的前 50 個分片物理庫表(同樣未產生跨機房)。
現實情況中,由于上海非金地域中 ODP 實例僅支持可用區 A、C、D,暫時不支持部署在可用區 E、F、G,而 OceanBase 目前僅支持機房 E、F、G 作為主可用區,因此暫時匹配不上,從而出現跨機房訪問。
對于三可用區的 OB 集群而言,每個可用區均分布一臺 OBServer。在主可用區為 A 的租戶中創建的所有分區,其 leader 均為可用區 A;如某個分區的 leader 為可用區 A,則讀寫該分區時都默認訪問位于可用區 A 的 OBServer。
前 50 分片的 leader 所在可用區 A 宕機后,OB 會將該 50 分片的 leader 切換至可用區 B,并且應用流量也會全部調撥到可用區 B。此時,依然可以為 100 個分片提供數據訪問服務(OB 多副本機制)。
前置條件
開通數據訪問代理(ODP)組件服務。
在華東 2(上海)地域創建一個專有網絡 VPC,并在上海可用區 A 和可用區 C 分別創建一個虛擬交換機 vSwitch。詳見 搭建專有網絡。
購買 ODP 實例
登錄 ODP 控制臺頁面,左側導航欄選擇 實例,單擊 創建實例。
在實例購買頁面,選擇地域、可用區、實例規格以及類型等。
地域:選擇華東2(上海)。
可用區:選擇上海非金可用區-A。
實例規格:選擇 8 核 16 GB。
類型:選擇 OceanBase。
專有網絡:選擇之前創建好的 VPC。
虛擬交換機:選擇位于上海可用區 A 的虛擬交換機實例 ID。
說明請盡量選擇 ODP 實例所在可用區的虛擬交換機。如果 ODP與應用不在同一可用區,或者 ODP 沒有映射到應用所在可用區的虛擬交換機,應用訪問 ODP 時則需要進行跨可用區訪問,將會導致較高的延時問題。
單擊 立即購買 進入購買預覽頁面。
確認訂單信息無誤并閱讀產品服務條款后,勾選 數據訪問代理服務協議,單擊 去開通 完成購買。
在購買成功后的提示頁面,單擊 管理控制臺 返回 ODP 實例列表,可以看到剛剛創建的 ODP 實例。
單擊該實例 ID 進入其詳情頁,您可以看到已有的一個機房,單擊詳情頁右上角的 添加機房,為該邏輯實例添加第二個機房。
在新頁面中,選擇當前地域的另外一個可用區,如 上海非金可用區-C,且虛擬交換機也需選擇位于可用區 C 的虛擬交換機實例 ID。
購買后,返回該實例詳情頁,即可看到已存在兩個機房。此時,該邏輯實例便對應了兩個物理實例(即邏輯實例在某一個機房中的真實實例),分別部署在上海非金可用區 A 和上海非金可用區 C,兩個物理實例共享相同的元信息配置。
添加物理數據節點
登錄 OceanBase 管理控制臺,創建一個集群與兩個租戶,并設置主可用區分別為 華東 2(上海)可用區 E 和 F。詳見 創建集群 與 創建租戶。
將 ODP 地址加入到該 OceanBase 集群的白名單中:
在 ODP 控制臺 > 運維 > 物理數據節點 頁面,點擊 添加節點,在彈出窗口中,獲取 數據訪問代理地址。
返回 OB 集群工作臺,單擊 集群白名單 欄旁邊的編輯圖標,添加該 ODP 地址。
為該 OB 集群下的兩個租戶分別創建一個超級賬號。詳見 新建賬號。
返回 ODP 控制臺 > 運維 > 物理數據節點 頁面,分別添加兩個租戶的數據節點。
物理數據節點 ID:格式為
masterintranet + 租戶 ID
,如masterintranett22okxxxxxxxx
。鏈接地址:輸入該物理數據節點的訪問地址。
數據庫類型:選擇 OceanBase。
網絡類型:選擇 專有網絡。
VPC ID:輸入物理節點所在專有網絡 VPC 的 ID。
添加完成后,在物理數據節點列表,即可看到這兩個節點。
創建邏輯庫與物理庫
進入 ODP 控制臺 > 數據庫 頁面,單擊 創建數據庫。
在彈出的 創建數據庫 窗口中,選擇正確的 ODP 實例,單擊 創建。
在 選擇數據節點 頁面,選擇剛剛添加的兩個物理數據節點。
單擊 下一步,根據提示,填寫或選擇基本信息。根據本文的示例場景,需將 物理分庫數 設置為 100,如下圖所示。
單擊 下一步,進入建庫預覽,確認各項信息無誤后,選擇 所有數據節點使用不同賬號,并為兩個數據節點配置賬號信息,如下圖所示。
信息確認完畢,單擊 創建 開始創建數據庫。
進入該數據庫詳情頁,您可以查看到對應可用區-A(實際為 E)的租戶承載前 50 分片,對應可用區-C(實際為 F)的租戶承載后 50 分片。
創建邏輯表與物理表
在剛剛創建的數據庫詳情頁,單擊右側頁面下方的 新增數據表。
進入創建數據表向導,填寫或選擇各項數據表信息,勾選 現在創建物理表,并點擊 下一步。示例:以 user 表為例,創建拆分表,分表數為 100,分表規則為 MySQL 風格的字符串截斷(-2 ~ 2),即取
user_id
字符串的最后兩位作為sharding_key
(分庫分表位)。輸入 DDL 語句來進行創建數據表,單擊 執行。
返回數據庫詳情頁,單擊右上角的 配置生效,并 確定。
應用連接邏輯庫
在業務 VPC 內,您可以直接使用內網地址訪問 ODP。您也可以申請公網地址,然后在本地通過 MySQL CLI 來訪問 ODP。
使用邏輯庫中的 MYSQL 客戶端命令行命令,即可訪問某個可用區的 ODP 實例中的邏輯庫。
執行 show topology from $tableName
,即可查看某張邏輯表的拓撲結構,如下圖所示。
應用可以通過 dbp-connector 較為便捷地訪問雙機房 ODP。詳細的配置方法,可參見 配置同城雙活模式。
配置時,需要特別注意以下幾點:
在引入 dbp-connector 的依賴時,版本號必須是 1.1.1 及以上。
在配置連接池時,
url
配置的格式為jdbc:mysql://${阿里云 ODP 實例 ID}@zone@.sofaodp.aliyuncs.com:8306/${數據庫名稱}
。<bean id="simpleDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://${yourDbpInstanceId}@zone@.sofaodp.aliyuncs.com:8306/${yourDatabase}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </bean>
配置與訪問示例
修改 Spring 文件。本文示例如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd" default-autowire="byName"> <bean id="dbpDiscovery"class="com.alipay.sofa.dbp.discovery.DbpDiscovery"/> <bean id="simpleDataSourceConnector"class="com.alipay.sofa.dbp.DbpDataSource" init-method="init"> <property name="delegate" ref="simpleDataSource"/> <property name="appName" value="ldc_demo_app"/> <property name="database" value="ldc_demo"/> <property name="dbpInstanceId" value="sofaodp-l8eh5cdite4w"/> <property name="clientTracer" ref="clientTracer"/> </bean> <!-- dataSource pool --> <bean id="simpleDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <!-- 這里為了本地測試使用了公網域名,實際應用部署時應該使用內網域名,即不帶public --> <property name="url" value="jdbc:mysql://sofaodp-lxxxxxxxtest@zone@.public.sofaodp.aliyuncs.com:8306/ldc_demo"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </bean> <bean id="clientTracer" class="com.alipay.sofa.dbp.DbpClientTracer"> <!-- 設置客戶端日志才樣的閾值,默認3ms(3ms內成功的sql按10%采樣),設置為0 全部打印 --> <property name="sampleThreshold" value="3"/> </bean> </beans>
在應用代碼(以 Java 為例)中,測試插入一條位于 23 分片的記錄,然后查詢該條記錄。示例如下:
public class DbpConnectorAliyunTest extends AbstractTestBase{ @Autowired @Qualifier("simpleDataSourceConnector") private DataSource dataSource; static{ // 應用部署時,發布部署系統會自動為您注入此系統變量為當前可用區,無需手動設置,此處僅為演示 System.setProperty("com.alipay.ldc.datacenter","cn-shanghai-a"); } @Test public void test() throws SQLException{ // user_id的最后兩位為分片值,即當前這條數據要落到23分片 String userId ="隨機生成的數字串23"; String username ="user23"; String insertSql ="insert into user (id, user_id, username) values (?, ?, ?)"; Connection connection = dataSource.getConnection(); PreparedStatement insertStmt = connection.prepareStatement(insertSql); insertStmt.setInt(1,0); insertStmt.setString(2, userId); insertStmt.setString(3, username); insertStmt.executeUpdate(); insertStmt.close(); String querySql ="select username from user where user_id = ?"; PreparedStatement queryStmt = connection.prepareStatement(querySql); queryStmt.setString(1, userId); ResultSet resultSet = queryStmt.executeQuery(); resultSet.next(); Assert.assertEquals(username, resultSet.getString(1)); } }
連接至物理庫,驗證數據路由的正確性。