日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Sharding-JDBC(二)2.0.3版本实践

發布時間:2025/3/21 编程问答 52 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Sharding-JDBC(二)2.0.3版本实践 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

  一、Sharding-JDBC依賴

  二、分片策略

    1. 標準分片策略

    2. 復合分片策略

    3. Inline表達式分片策略

    4. 通過Hint而非SQL解析的方式分片的策略

    5. 不分片的策略

  三、分片鍵

  四、分片算法

    1. 精確分片算法

    2. 范圍分片算法

    3. 復合分片算法

    4. Hint分片算法

  五、代碼實踐

?

上一篇博文以Sharding-JDBC為契機,了解了ShardingSphere大家族的全貌概覽,以及Sharding-JDBC的角色定位。

Sharding-JDBC定位為輕量級Java框架,在Java的JDBC層提供的額外服務。 它使用客戶端直連數據庫,以jar包形式提供服務,無需額外部署和依賴,可理解為增強版的JDBC驅動,完全兼容JDBC和各種ORM框架。

Sharding-JDBC目前已經迭代到4.0.0版本,并且進入了Apache孵化器,但Sharding-JDBC各個大版本之間不支持向下兼容(這里主要描述的是2.x到4.x),大版本和大版本之間猶如斷層,如果涉及到升級,就需要改動代碼,并且2.x到4.x多多少少都有點BUG,導致在業務系統引進Sharding-JDBC的過程略顯艱難。

接下來將介紹Sharding-JDBC的2.0.3版本,以及它的長處和短板。

一、Sharding-JDBC依賴

<!-- sharding-jdbc-core --> <dependency><groupId>io.shardingjdbc</groupId><artifactId>sharding-jdbc-core</artifactId><version>2.0.3</version> </dependency> <!-- sharding-jdbc-spring-namespace --> <dependency><groupId>io.shardingjdbc</groupId><artifactId>sharding-jdbc-core-spring-namespace</artifactId><version>2.0.3</version> </dependency>

Sharding-JDBC沒有將Spring Schema上傳至公網,需引入namespace依賴包。

二、分片策略

包含分片鍵和分片算法,由于分片算法的獨立性,將其獨立抽離。真正可用于分片操作的是分片鍵 + 分片算法,也就是分片策略。目前提供5種分片策略:標準分片策略、復合分片策略、Inline表達式分片策略、通過Hint而非SQL解析的方式分片的策略和不分片的策略。

1. 標準分片策略

對應StandardShardingStrategy。提供對SQL語句中的=、IN和BETWEEN AND的分片操作支持。StandardShardingStrategy只支持單分片鍵,提供PreciseShardingAlgorithm和RangeShardingAlgorithm兩個分片算法。PreciseShardingAlgorithm是必選的,用于處理=和IN的分片。RangeShardingAlgorithm是可選的,用于處理BETWEEN AND分片,如果不配置RangeShardingAlgorithm,SQL中的BETWEEN AND將按照全庫路由處理。

2.?復合分片策略

對應ComplexShardingStrategy。復合分片策略。提供對SQL語句中的=、IN和BETWEEN AND的分片操作支持。ComplexShardingStrategy支持多分片鍵,由于多分片鍵之間的關系復雜,因此并未進行過多的封裝,而是直接將分片鍵值組合以及分片操作符透傳至分片算法,完全由應用開發者實現,提供最大的靈活度。

3.?Inline表達式分片策略

對應InlineShardingStrategy。使用Groovy的表達式,提供對SQL語句中的=和IN的分片操作支持,只支持單分片鍵。對于簡單的分片算法,可以通過簡單的配置使用,從而避免繁瑣的Java代碼開發,如??t_user_$->{u_id % 8}??表示t_user表根據u_id模8,而分成8張表,表名稱為?t_user_0?到?t_user_7?。

4.?通過Hint而非SQL解析的方式分片的策略

對應HintShardingStrategy。通過Hint而非SQL解析的方式分片的策略。

5.?不分片的策略

對應NoneShardingStrategy。不分片的策略。

標準分片策略、復合分片策略和Inline表達式分片策略要求分片鍵(即分片字段)必須存在于SQL中和數據表結構中,否則無法正確分片;相反,若分片鍵不存在于SQL中和數據表結構中,則可以使用Hint方式進行強制路由。

三、分片鍵

用于分片的數據庫字段,是將數據庫(表)水平拆分的關鍵字段。例:將訂單表中的訂單主鍵的尾數取模分片,則訂單主鍵為分片字段。 SQL中如果無分片字段,將執行全路由,性能較差。 除了對單分片字段的支持,ShardingSphere也支持根據多個字段進行分片。

四、分片算法

通過分片算法將數據分片,支持通過=、IN和BETWEEN AND分片。分片算法需要應用方開發者自行實現,可實現的靈活度非常高。

目前提供4種分片算法。由于分片算法和業務實現緊密相關,因此并未提供內置分片算法,而是通過分片策略將各種場景提煉出來,提供更高層級的抽象,并提供接口讓應用開發者自行實現分片算法。

1. 精確分片算法

對應PreciseShardingAlgorithm,用于處理使用單一鍵作為分片鍵的=與IN進行分片的場景。需要配合StandardShardingStrategy使用。

2. 范圍分片算法

對應RangeShardingAlgorithm,用于處理使用單一鍵作為分片鍵的BETWEEN AND進行分片的場景。需要配合StandardShardingStrategy使用。

3. 復合分片算法

對應ComplexKeysShardingAlgorithm,用于處理使用多鍵作為分片鍵進行分片的場景,包含多個分片鍵的邏輯較復雜,需要應用開發者自行處理其中的復雜度。需要配合ComplexShardingStrategy使用。

4. Hint分片算法

對應HintShardingAlgorithm,用于處理使用Hint行分片的場景。需要配合HintShardingStrategy使用。

五、代碼實踐

在正式介紹代碼之前,有必要先描述下業務背景,便于理解代碼的用途。

數據表結構:

CREATE TABLE `settlement_20180403` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`pay_serial_number` varchar(32) DEFAULT NULL COMMENT '支付流水號',`user_mobile` varchar(15) DEFAULT NULL COMMENT '用戶手機號',`money` int(10) DEFAULT '0' COMMENT '支付或退款金額, 單位: 分',`operate_tm` timestamp NULL DEFAULT NULL COMMENT '操作時間',`refund` tinyint(1) DEFAULT NULL COMMENT '是否退款 1: 是 2: 否',`remark` varchar(32) DEFAULT NULL COMMENT '備注',PRIMARY KEY (`id`),UNIQUE KEY `PAY_SERIAL_NUM_UNIQUE` (`pay_serial_number`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

表結構中比較有趣的字段是?pay_serial_number?,以?232042018040353088?為例,?pay_serial_number?由三部分組成:前5位是固定編碼,樣例中是23204,中間8位是日期,包含年月日,樣例中是20180403,最后5位是隨機數,樣例中是53088,以上三部分組成了支付流水號。

隨著業務量逐漸擴增,?settlement?表數據量急劇,需要以時間作為分表條件水平切分數據,分表字段則為?pay_serial_number?,其中的日期則為分表條件。接下來的代碼都是以此業務背景展開。

如下代碼配置了標準分片策略中的精確分片算法PreciseShardingAlgorithm和Hint分片算法HintShardingAlgorithm。

XML配置:

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:sharding="http://shardingjdbc.io/schema/shardingjdbc/sharding"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsdhttp://shardingjdbc.io/schema/shardingjdbc/shardinghttp://shardingjdbc.io/schema/shardingjdbc/sharding/sharding.xsd"><!-- 標準分片策略 --><sharding:standard-strategy id="settlementTableShardingStandardStrategy" sharding-column="pay_serial_number"precise-algorithm-class="org.cellphone.finance.repo.sharding.PreciseTableShardingAlgorithm"/><!-- 基于暗示(Hint)的數據分片策略 --><sharding:hint-strategy id="settlementTableShardingHintStrategy"algorithm-class="org.cellphone.finance.repo.sharding.HintTableShardingAlgorithm"/><!-- 加了分庫分表插件,spring boot 啟動會實例化兩個dataSource,不知是否正常? --><sharding:data-source id="shardingDataSource"><!-- dataSource是數據庫連接池 --><sharding:sharding-rule data-source-names="dataSource"><sharding:table-rules><sharding:table-rule logic-table="settlement"table-strategy-ref="settlementTableShardingStandardStrategy"/><!-- logic-table 一定要和SQL中的表名以及HintManager中配置的logicTable一致,否則無法找到對應的table rule --><sharding:table-rule logic-table="settlement_hint"table-strategy-ref="settlementTableShardingHintStrategy"/></sharding:table-rules></sharding:sharding-rule><sharding:props><prop key="sql.show">true</prop></sharding:props></sharding:data-source><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="shardingDataSource"/></bean><tx:annotation-driven/> </beans>

?精確分片算法:

package org.cellphone.finance.repo.sharding;import com.google.common.collect.Lists; import io.shardingjdbc.core.api.algorithm.sharding.PreciseShardingValue; import io.shardingjdbc.core.api.algorithm.sharding.standard.PreciseShardingAlgorithm; import org.apache.commons.collections.CollectionUtils; import org.cellphone.common.constant.CommonConst;import java.util.Collection;/*** 精確分片算法,屬于標準分片算法,用于處理=和IN的分片* <p>* 使用精確分片算法的前提:分片字段必須存在與SQL中、數據庫表結構中,否則無法使用精確分片算法* <p>* 此分片算法應用于SETTLEMENT數據表,這里是按天分表* <p>* 特別說明:Sharding Jdbc版本:2.0.3* <p>* Created by on 2018/4/9.*/ public class PreciseTableShardingAlgorithm implements PreciseShardingAlgorithm<String> {/*** 精確分片算法** @param availableTargetNames 目標數據源名稱或數據表名稱,注意:是邏輯數據源名或邏輯數據表名,來自SQL* @param shardingValue 分片值,來自SQL中分片字段對應的值* @return 真實數據源名稱或數據表名稱*/@Overridepublic String doSharding(final Collection<String> availableTargetNames, final PreciseShardingValue<String> shardingValue) {// 默認數據表名稱,有可能數據庫中不存在這張表String tableName = "settlement";// 邏輯表名為空,返回默認表名if (CollectionUtils.isEmpty(availableTargetNames))return tableName;// availableTargetNames來自SQL,只有一個元素tableName = Lists.newArrayList(availableTargetNames).get(0);String paySerialNumber = shardingValue.getValue();String suffix = paySerialNumber.substring(5, 13);return tableName + CommonConst.UNDERLINE + suffix;} }

上面說過,精確分片算法可以很完美的支持SQL語句中的=和IN的分片操作,因此PreciseTableShardingAlgorithm可以很好的支持簡單的INSERT、UPDATE、DELETE和SELECT操作。

但如果要通過?pay_serial_number?查詢數據就行不通了,因為分片鍵并不直接存在與SQL中和數據表結構中,而是間接存在于?pay_serial_number?中的時間數據,因此,就需要通過Hint方式來進行分片才能定位到真實的數據表。

Hint分片算法:

package org.cellphone.finance.repo.sharding;import com.google.common.collect.Lists; import io.shardingjdbc.core.api.algorithm.sharding.ListShardingValue; import io.shardingjdbc.core.api.algorithm.sharding.ShardingValue; import io.shardingjdbc.core.api.algorithm.sharding.hint.HintShardingAlgorithm; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.DateFormatUtils; import org.apache.commons.lang3.time.DateUtils; import org.cellphone.common.constant.CommonConst; import org.cellphone.common.constant.DateConst;import java.text.ParseException; import java.util.*;/*** Created by on 2019/4/27.*/ public class HintTableShardingAlgorithm implements HintShardingAlgorithm {@Overridepublic Collection<String> doSharding(Collection<String> availableTargetNames, ShardingValue shardingValue) {// 數據表名稱列表List<String> tableNames = new ArrayList<>();// 邏輯表名為空if (CollectionUtils.isEmpty(availableTargetNames))return tableNames;// availableTargetNames來自SQL,只有一個元素String tableName = Lists.newArrayList(availableTargetNames).get(0);tableName = tableName.replace("_hint", StringUtils.EMPTY);ListShardingValue<String> listShardingValue = (ListShardingValue<String>) shardingValue;List<String> list = Lists.newArrayList(listShardingValue.getValues());Date startTm, endTm;try {startTm = DateUtils.parseDate(list.get(0), DateConst.DATE_FORMAT_NORMAL);endTm = DateUtils.parseDate(list.get(1), DateConst.DATE_FORMAT_NORMAL);} catch (ParseException e) {return tableNames;}Calendar calendar = Calendar.getInstance();while (startTm.getTime() <= endTm.getTime()) {String suffix = DateFormatUtils.format(startTm, DateConst.DATE_FORMAT_YYYY_MM_DD);tableNames.add(tableName + CommonConst.UNDERLINE + suffix);calendar.setTime(startTm);calendar.add(Calendar.DATE, 1);startTm = calendar.getTime();}return tableNames;} }

與Hint分片算法對應的Java查詢方法?settlementMapper.selectByExample(example)?:

public List<Settlement> querySettlements(SettlementExample example, String startTime, String endTime) {HintManager hintManager = HintManager.getInstance();// logicTable必須和XML中的logic-table以及SQL中的邏輯表名稱一致hintManager.addTableShardingValue("settlement_hint", "start_time", startTime);hintManager.addTableShardingValue("settlement_hint", "end_time", endTime);List<Settlement> settlements = settlementMapper.selectByExample(example);hintManager.close();return settlements; }

以及該查詢方法對應的SQL語句:

select * from settlement_hint t where t.pay_serial_number = ?

?單元測試代碼:

@Test public void test004QuerySettlements() throws ParseException {String startTime = "2018-04-03 00:00:00", endTime = "2018-04-05 00:00:00";SettlementExample example = new SettlementExample();SettlementExample.Criteria criteria = example.createCriteria();criteria.andPaySerialNumberEqualTo("232042018040353088");List<Settlement> settlements = repository.querySettlements(example, startTime, endTime);Assert.assertEquals("136********", settlements.get(0).getUserMobile()); }

?經過上述一波代碼后,原以為單元測試可以完美通過,但天有不測風云,月有陰晴圓缺,單元測試竟然失敗了,報錯日志提示數據表不存在:

org.springframework.jdbc.BadSqlGrammarException: ### Error querying database. Cause: java.sql.SQLSyntaxErrorException: Table 'warehouse.settlement_hint' doesn't exist ### The error may exist in file [D:\programs\IdeaProjects\warehouse\warehouse-finance\warehouse-finance-service\target\classes\mapper\SettlementMapper.xml] ### The error may involve org.cellphone.finance.repo.mapper.SettlementMapper.selectByExample-Inline ### The error occurred while setting parameters ### SQL: select id, pay_serial_number, user_mobile, money, operate_tm, refund, remark from settlement_hint WHERE ( pay_serial_number = ? ) ### Cause: java.sql.SQLSyntaxErrorException: Table 'warehouse.settlement_hint' doesn't exist ; bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException: Table 'warehouse.settlement_hint' doesn't existat org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:234)at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:73)at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:446)at com.sun.proxy.$Proxy94.selectList(Unknown Source)at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:230)at org.apache.ibatis.binding.MapperMethod.executeForMany(MapperMethod.java:139)at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:76)at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59)at com.sun.proxy.$Proxy95.selectByExample(Unknown Source)at org.cellphone.finance.repo.SettlementRepository.querySettlements(SettlementRepository.java:62)at org.cellphone.finance.repo.SettlementRepository$$FastClassBySpringCGLIB$$c5ad592f.invoke(<generated>)at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746)at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)at org.cellphone.finance.repo.SettlementRepository$$EnhancerBySpringCGLIB$$9133dcc1.querySettlements(<generated>)at org.cellphone.finance.SettlementRepositoryTest.test004QuerySettlements(SettlementRepositoryTest.java:89)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:498)at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:73)at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:83)at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)at org.junit.runners.ParentRunner.run(ParentRunner.java:363)at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)at org.junit.runner.JUnitCore.run(JUnitCore.java:137)at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) Caused by: java.sql.SQLSyntaxErrorException: Table 'warehouse.settlement_hint' doesn't existat com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120)at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:975)at com.mysql.cj.jdbc.ClientPreparedStatement.execute(ClientPreparedStatement.java:392)at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_execute(FilterChainImpl.java:3409)at com.alibaba.druid.filter.FilterEventAdapter.preparedStatement_execute(FilterEventAdapter.java:440)at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_execute(FilterChainImpl.java:3407)at com.alibaba.druid.proxy.jdbc.PreparedStatementProxyImpl.execute(PreparedStatementProxyImpl.java:167)at com.alibaba.druid.pool.DruidPooledPreparedStatement.execute(DruidPooledPreparedStatement.java:498)at io.shardingjdbc.core.executor.type.prepared.PreparedStatementExecutor$3.execute(PreparedStatementExecutor.java:101)at io.shardingjdbc.core.executor.type.prepared.PreparedStatementExecutor$3.execute(PreparedStatementExecutor.java:97)at io.shardingjdbc.core.executor.ExecutorEngine.executeInternal(ExecutorEngine.java:187)at io.shardingjdbc.core.executor.ExecutorEngine.syncExecute(ExecutorEngine.java:167)at io.shardingjdbc.core.executor.ExecutorEngine.execute(ExecutorEngine.java:131)at io.shardingjdbc.core.executor.ExecutorEngine.executePreparedStatement(ExecutorEngine.java:98)at io.shardingjdbc.core.executor.type.prepared.PreparedStatementExecutor.execute(PreparedStatementExecutor.java:97)at io.shardingjdbc.core.jdbc.core.statement.ShardingPreparedStatement.execute(ShardingPreparedStatement.java:141)at org.apache.ibatis.executor.statement.PreparedStatementHandler.query(PreparedStatementHandler.java:63)at org.apache.ibatis.executor.statement.RoutingStatementHandler.query(RoutingStatementHandler.java:79)at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:63)at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:326)at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:156)at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:109)at com.github.pagehelper.PageInterceptor.intercept(PageInterceptor.java:108)at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:61)at com.sun.proxy.$Proxy117.query(Unknown Source)at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:148)at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:141)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:498)at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:433)... 46 more

拋出錯誤堆棧后,很納悶為何沒有將邏輯表名?settlement_hint?轉換為真實表名?settlement_20180403?,于是就跟蹤了Sharding-JDBC源碼。

經過DEBUG,得知所有JDBC操作都會調用?io.shardingjdbc.core.routing.type.simple.SimpleRoutingEngine#route?方法:

/** Copyright 1999-2015 dangdang.com.* <p>* Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.* </p>*/package io.shardingjdbc.core.routing.type.simple;import io.shardingjdbc.core.api.algorithm.sharding.ShardingValue; import io.shardingjdbc.core.hint.HintManagerHolder; import io.shardingjdbc.core.hint.ShardingKey; import io.shardingjdbc.core.parsing.parser.context.condition.Column; import io.shardingjdbc.core.parsing.parser.context.condition.Condition; import io.shardingjdbc.core.parsing.parser.sql.SQLStatement; import io.shardingjdbc.core.routing.strategy.ShardingStrategy; import io.shardingjdbc.core.routing.type.RoutingEngine; import io.shardingjdbc.core.routing.type.RoutingResult; import io.shardingjdbc.core.routing.type.TableUnit; import io.shardingjdbc.core.rule.DataNode; import io.shardingjdbc.core.rule.ShardingRule; import io.shardingjdbc.core.rule.TableRule; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import lombok.RequiredArgsConstructor;import java.util.ArrayList; import java.util.Collection; import java.util.LinkedList; import java.util.List;/*** Simple routing engine.** @author zhangliang*/ @RequiredArgsConstructor public final class SimpleRoutingEngine implements RoutingEngine {private final ShardingRule shardingRule;private final List<Object> parameters;private final String logicTableName;private final SQLStatement sqlStatement;/*** Sharding-JDBC路由方法,所有JDBC操作都會調用此方法,路由到真實表** @return*/@Overridepublic RoutingResult route() {// 從XML中根據邏輯表名獲取配置的數據表規則TableRule tableRule = shardingRule.getTableRule(logicTableName);// 獲取數據源分片值,分片值來自邏輯SQL中的數據,由于XML只配置了單個數據源,暫時不深入分析此環節List<ShardingValue> databaseShardingValues = getDatabaseShardingValues(tableRule);// 獲取數據表分片值,分片值來自邏輯SQL中的數據,重點分析這部分代碼List<ShardingValue> tableShardingValues = getTableShardingValues(tableRule);// 計算需要路由的真實數據源Collection<String> routedDataSources = routeDataSources(tableRule, databaseShardingValues);Collection<DataNode> routedDataNodes = new LinkedList<>();for (String each : routedDataSources) {// routeTables方法計算需要路由的真實數據表,重點分析這部分代碼routedDataNodes.addAll(routeTables(tableRule, each, tableShardingValues));}// 產生路由結果return generateRoutingResult(routedDataNodes);}private List<ShardingValue> getDatabaseShardingValues(final TableRule tableRule) {ShardingStrategy strategy = shardingRule.getDatabaseShardingStrategy(tableRule);return HintManagerHolder.isUseShardingHint() ? getDatabaseShardingValuesFromHint(strategy.getShardingColumns()) : getShardingValues(strategy.getShardingColumns());}/*** 獲取數據表分片值* 分片值由上面提到的querySettlements通過hintManager傳入** @param tableRule 數據表規則,從XML文件中獲取* @return 分片值列表*/private List<ShardingValue> getTableShardingValues(final TableRule tableRule) {// 從XML文件中獲取數據表規則ShardingStrategy strategy = shardingRule.getTableShardingStrategy(tableRule);/** 判斷是否使用了Hint分片算法:* 1. 是:根據ShardingStrategy中拿到的shardingColumns來獲取shardingValues,問題就出在這里!!!* 2. 否:從SQL中根據shardingColumns來獲取shardingValues*/return HintManagerHolder.isUseShardingHint() ? getTableShardingValuesFromHint(strategy.getShardingColumns()) : getShardingValues(strategy.getShardingColumns());}private List<ShardingValue> getDatabaseShardingValuesFromHint(final Collection<String> shardingColumns) {List<ShardingValue> result = new ArrayList<>(shardingColumns.size());for (String each : shardingColumns) {Optional<ShardingValue> shardingValue = HintManagerHolder.getDatabaseShardingValue(new ShardingKey(logicTableName, each));if (shardingValue.isPresent()) {result.add(shardingValue.get());}}return result;}/*** 從Hint分片算法中獲取shardingValues** @param shardingColumns 分片鍵* @return 分片值列表*/private List<ShardingValue> getTableShardingValuesFromHint(final Collection<String> shardingColumns) {List<ShardingValue> result = new ArrayList<>(shardingColumns.size());for (String each : shardingColumns) {// 從HintManagerHolder獲取sharding valuesOptional<ShardingValue> shardingValue = HintManagerHolder.getTableShardingValue(new ShardingKey(logicTableName, each));if (shardingValue.isPresent()) {result.add(shardingValue.get());}}return result;}private List<ShardingValue> getShardingValues(final Collection<String> shardingColumns) {List<ShardingValue> result = new ArrayList<>(shardingColumns.size());for (String each : shardingColumns) {Optional<Condition> condition = sqlStatement.getConditions().find(new Column(each, logicTableName));if (condition.isPresent()) {result.add(condition.get().getShardingValue(parameters));}}return result;}private Collection<String> routeDataSources(final TableRule tableRule, final List<ShardingValue> databaseShardingValues) {Collection<String> availableTargetDatabases = tableRule.getActualDatasourceNames();if (databaseShardingValues.isEmpty()) {return availableTargetDatabases;}Collection<String> result = shardingRule.getDatabaseShardingStrategy(tableRule).doSharding(availableTargetDatabases, databaseShardingValues);Preconditions.checkState(!result.isEmpty(), "no database route info");return result;}/*** 計算需要路由的真實數據表** @param tableRule 數據表規則,從XML中獲取* @param routedDataSource 需要路由的數據源* @param tableShardingValues 數據表分片值* @return 需要路由的真實數據節點*/private Collection<DataNode> routeTables(final TableRule tableRule, final String routedDataSource, final List<ShardingValue> tableShardingValues) {// 所有的真實數據表名,在XML中可以顯式配置,也可以省略Collection<String> availableTargetTables = tableRule.getActualTableNames(routedDataSource);/** table sharding values是否為空:* 1. 是:路由到所有真實表* 2. 否:路由到自定義的分表策略算法定義的數據表** 問題就出在這里:tableShardingValues.isEmpty()為true,導致無法使用自定義分表策略算法*/Collection<String> routedTables = tableShardingValues.isEmpty() ? availableTargetTables: shardingRule.getTableShardingStrategy(tableRule).doSharding(availableTargetTables, tableShardingValues);Preconditions.checkState(!routedTables.isEmpty(), "no table route info");Collection<DataNode> result = new LinkedList<>();for (String each : routedTables) {result.add(new DataNode(routedDataSource, each));}return result;}private RoutingResult generateRoutingResult(final Collection<DataNode> routedDataNodes) {RoutingResult result = new RoutingResult();for (DataNode each : routedDataNodes) {result.getTableUnits().getTableUnits().add(new TableUnit(each.getDataSourceName(), logicTableName, each.getTableName()));}return result;} }

?上述代碼中,?getTableShardingValuesFromHint?返回的?List<ShardingValue>?為空,原因是?getTableShardingValuesFromHint?的入參?strategy.getShardingColumns()?為空列表,而此參數來自Sharding-JDBC的默認實現HintShardingStrategy:

/** Copyright 1999-2015 dangdang.com.* <p>* Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.* </p>*/package io.shardingjdbc.core.routing.strategy.hint;import io.shardingjdbc.core.api.algorithm.sharding.hint.HintShardingAlgorithm; import io.shardingjdbc.core.api.algorithm.sharding.ShardingValue; import io.shardingjdbc.core.routing.strategy.ShardingStrategy; import lombok.Getter;import java.util.Collection; import java.util.TreeSet;/*** Hint sharding strategy.* final類,無法繼承此類來重定義內部邏輯* * * @author zhangliang*/ public final class HintShardingStrategy implements ShardingStrategy {/*** 沒有提供Setter方法和可以配置的入口,無法設置shardingColumns,這是2.0.3版本的BUG* * github issue: https://github.com/apache/incubator-shardingsphere/issues/1980*/@Getterprivate final Collection<String> shardingColumns;private final HintShardingAlgorithm shardingAlgorithm;public HintShardingStrategy(final HintShardingAlgorithm shardingAlgorithm) {this.shardingColumns = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);this.shardingAlgorithm = shardingAlgorithm;}@Overridepublic Collection<String> doSharding(final Collection<String> availableTargetNames, final Collection<ShardingValue> shardingValues) {Collection<String> shardingResult = shardingAlgorithm.doSharding(availableTargetNames, shardingValues.iterator().next());Collection<String> result = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);result.addAll(shardingResult);return result;} }

跟蹤到此,Hint分片算法無法使用的原因一路了然,這是Sharding-JDBC 2.0.3版本的BUG,但在后續版本4.x中得到了修復。

總結

以上是生活随笔為你收集整理的Sharding-JDBC(二)2.0.3版本实践的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

中文字幕在线观看完整 | 午夜色大片在线观看 | 超碰97中文 | 五月天综合婷婷 | 国产成人久久av免费高清密臂 | 久久99视频免费观看 | 亚洲一级国产 | 在线日本看片免费人成视久网 | 国产黄色大片免费看 | 正在播放 久久 | 中文字幕第 | 久久久久免费 | 五月开心婷婷 | 久久精品99久久久久久 | 国产成人亚洲在线电影 | 国产一级视频免费看 | 亚洲午夜精 | 国产黄色免费在线观看 | 国产黄大片在线观看 | 久艹在线观看视频 | 97理论片 | 久久综合桃花 | 韩国精品一区二区三区六区色诱 | 美女网站黄免费 | 日韩高清久久 | 四虎国产精品成人免费影视 | 亚洲乱码国产乱码精品天美传媒 | 国产精彩视频一区二区 | www.国产在线 | 午夜成人免费影院 | 日韩精品一区二区在线 | 91色亚洲| 激情偷乱人伦小说视频在线观看 | 国产精品视频在线观看 | 国产麻豆剧传媒免费观看 | 国产精品成人国产乱一区 | 国产精品第十页 | 久久你懂得 | 成+人+色综合 | 国产一级视频在线观看 | 五月婷婷六月丁香在线观看 | 午夜精品久久久久久久99无限制 | 久久线视频 | 美女中文字幕 | 91成人精品国产刺激国语对白 | 高清国产在线一区 | 香蕉久久久久久久 | 久久99九九99精品 | 久久视屏网| 亚洲激情综合网 | 日韩黄色中文字幕 | 国产又粗又硬又爽的视频 | 综合色久| 亚洲高清色综合 | 亚洲精品久久久久久中文传媒 | 五月天欧美精品 | 一区二区影院 | 中文字幕国产在线 | 人人添人人澡 | 久久国产免费视频 | 国产精品视频你懂的 | 亚洲黄网站 | 欧美一级日韩免费不卡 | 日韩午夜电影 | 99色在线播放 | 可以免费观看的av片 | 精品999国产| 91污视频在线 | 人人看人人 | 中文字幕永久免费 | 国产精品久久久久久久久搜平片 | 久久字幕精品一区 | 夜夜夜精品 | 欧美日韩aa| 六月丁香婷 | 国产精品99精品久久免费 | 中文字幕色在线 | 欧美日韩国产二区 | 亚洲国产成人av网 | 精品一区二区综合 | 91国内在线 | 午夜成人免费电影 | 看全黄大色黄大片 | 91精品啪在线观看国产线免费 | 成人国产精品免费 | 久久精品国产亚洲精品 | 91少妇精拍在线播放 | 奇米影视777四色米奇影院 | 国产黄免费在线观看 | 日韩视频中文字幕 | av黄色免费看 | 久久亚洲影院 | 国产精品专区在线 | www免费网站在线观看 | 久久99精品久久久久久久久久久久 | 国产不卡免费视频 | 丝袜足交在线 | 怡红院av| 在线播放91| 国产美女精品视频 | 久章操 | 日日夜夜操av | 国产91精品一区二区麻豆亚洲 | 免费看的黄色片 | 三级av免费看 | 天天操天天操 | 久草在线免费资源 | av线上免费看 | 99久久久久久久久久 | 97成人超碰| 中文在线字幕免费观 | 欧美精品久久久久久久久免 | 国产精品淫 | 欧美日韩久 | 免费视频91蜜桃 | 色婷婷a | 国产中文字幕网 | 2019免费中文字幕 | 久久视频在线观看中文字幕 | 91麻豆精品国产91久久久久久久久 | 97视频在线观看免费 | 夜夜操网 | 在线观看视频黄色 | 麻豆传媒视频在线免费观看 | 深爱激情亚洲 | 四虎国产免费 | 91成人黄色 | 日韩电影精品 | 97电影手机 | 人人干免费| 在线精品亚洲一区二区 | 操夜夜操 | 国产91电影在线观看 | 久久久久日本精品一区二区三区 | 国产va饥渴难耐女保洁员在线观看 | 在线成人中文字幕 | 9797在线看片亚洲精品 | 综合网色 | 国产资源在线视频 | 99久久久成人国产精品 | 国产码电影| 粉嫩高清一区二区三区 | 91久久久国产精品 | 久久99精品久久久久久秒播蜜臀 | 免费av影视 | 国内精品久久久久影院一蜜桃 | 99精品黄色片免费大全 | 99色资源| 日韩成人高清在线 | 深爱激情av | 成人久久影院 | 国产性xxxx | 久久精品99国产 | 中文字幕 91 | 国产精品18久久久久久久 | 国产精品v欧美精品 | 亚洲区另类春色综合小说校园片 | 人人插人人费 | 色噜噜在线观看 | 玖玖在线资源 | 成年人免费在线观看网站 | www.人人干| 五月激情站 | 国产伦理一区 | 国产一区免费在线 | 成人在线网站观看 | 日韩三级不卡 | 精品色999 | 亚洲97在线| 伊人五月婷| 黄网站app在线观看免费视频 | 亚洲网站在线看 | 天堂av免费 | 97韩国电影| 97精品国自产拍在线观看 | 国产高清无线码2021 | 在线视频 国产 日韩 | 欧美激情视频免费看 | 亚洲狠狠丁香婷婷综合久久久 | 久久国产精品一区二区 | 在线观看不卡视频 | 99久免费精品视频在线观看 | 91成人免费看 | 天天爱天天舔 | 亚洲成人免费 | 国产一区二区三区四区大秀 | 国产精品一区二区av日韩在线 | 91网址在线观看 | 欧美日韩国产一区二区三区在线观看 | 国产经典三级 | 2019中文最近的2019中文在线 | 在线观看视频一区二区三区 | 久久九九国产精品 | 国内精品久久久久影院男同志 | 成年人精品| 免费观看的黄色片 | 97超碰在线资源 | 色播六月天| 欧美日韩一二三四区 | 成人国产精品久久久春色 | 黄色视屏免费在线观看 | 国内揄拍国内精品 | 91精选在线观看 | 天天干 天天摸 天天操 | 久草综合在线观看 | 久久精品一区二 | 涩涩在线 | 国产区欧美 | 国产亚洲精品精品精品 | 又粗又长又大又爽又黄少妇毛片 | 久久九九精品久久 | 亚洲精品中文字幕在线观看 | 国外av在线| 婷婷电影在线观看 | 天天躁日日躁狠狠躁av麻豆 | 亚洲精品动漫在线 | 99久久婷婷国产综合亚洲 | 国产午夜精品一区二区三区在线观看 | 亚洲国产免费 | 91久久久久久久一区二区 | 操一草 | 黄色中文字幕在线 | 91精品久久久久久综合五月天 | 中文 一区二区 | 国产日韩精品一区二区在线观看播放 | 在线亚洲欧美视频 | 一区二区不卡高清 | av在线日韩 | 91在线看黄 | 色婷婷av一区 | 国内精品久久久久久久久久久久 | 国产在线久久久 | 91精品视频观看 | 欧美色就是色 | 亚洲精品一区二区三区在线观看 | 韩国av免费观看 | 久久久黄色免费网站 | 日本在线观看中文字幕无线观看 | 久久国产精品免费视频 | 国语黄色片| 日韩一区正在播放 | 日韩亚洲在线视频 | 久久爱影视i| 日本精品久久久久 | 久久久久久国产精品美女 | 探花视频免费观看 | 久久久久区 | 91九色在线播放 | 天天操 夜夜操 | 久久成人国产精品一区二区 | 亚洲精品国产品国语在线 | av在线免费不卡 | 四虎影视精品永久在线观看 | 超碰在线色 | 久久国产视频网 | 日本在线观看中文字幕无线观看 | 欧美福利网址 | 久久久久电影网站 | 午夜成人免费影院 | 欧美激情在线网站 | 成人免费在线观看电影 | 91福利视频久久久久 | 玖玖视频免费在线 | 91久久国产精品 | 色综合久久66 | 米奇四色影视 | 日韩在线观看一区二区三区 | 99久久99| 天天透天天插 | 色婷婷狠狠五月综合天色拍 | 天天操夜夜操天天射 | 久久久久久国产精品999 | 国产精品亚洲视频 | 久久av免费观看 | 亚洲一区黄色 | 91精品区 | 国产午夜精品一区二区三区在线观看 | 免费在线电影网址大全 | 在线观看色网站 | 免费观看9x视频网站在线观看 | 欧美激情第一区 | 国产亚洲精品久久久久秋 | 在线观看黄色大片 | 久久不射网站 | 人人狠狠综合久久亚洲 | 狠狠躁18三区二区一区ai明星 | 久久视频在线观看 | 精品一区 在线 | 狠狠的干狠狠的操 | 日日操天天射 | 免费福利在线观看 | 亚洲精品视频网址 | 国产精品女主播一区二区三区 | 日韩系列在线观看 | 麻豆极品| 国产最新视频在线 | 欧美少妇bbwhd | 欧美亚洲国产精品久久高清浪潮 | 精品亚洲欧美无人区乱码 | 看av在线| 免费网站黄色 | 婷婷爱五月天 | 色综合五月 | 国产成人精品一区二区 | 99久久精品免费看国产麻豆 | 黄色免费国产 | 久草在线视频资源 | 在线国产专区 | 最新中文在线视频 | 精品国产乱码久久 | 免费视频你懂的 | 911香蕉| 夜夜夜夜爽 | 999视频网站 | 亚洲欧美国产精品18p | 国产成人精品亚洲 | 久久爽久久爽久久av东京爽 | 日韩免费在线一区 | 中文字幕在线观看国产 | 免费在线观看污网站 | 99免费在线观看视频 | 日韩精品在线视频 | 91在线区| 国产91精品久久久久 | 久久久99国产精品免费 | 欧美小视频在线观看 | 国产999在线观看 | 九九在线视频免费观看 | 欧洲高潮三级做爰 | av一区二区三区在线观看 | 欧美激情精品久久久久久变态 | 久久久精品影视 | 久久国色夜色精品国产 | 黄色在线免费观看网站 | 91色吧| 91爱爱电影| 999国产精品视频 | 精品久久久久久亚洲 | 五月婷婷色综合 | 91av播放 | 成人aⅴ视频| 麻豆视频免费在线观看 | 黄色一级在线观看 | 中文一区二区三区在线观看 | 欧美日韩精品在线观看 | 成人av免费在线看 | 婷婷丁香激情五月 | 亚洲成a人片在线观看中文 中文字幕在线视频第一页 狠狠色丁香婷婷综合 | 9992tv成人免费看片 | 亚洲少妇激情 | 日韩高清一二三区 | 99热在线免费观看 | 一区二区三区四区久久 | 韩国三级av在线 | 亚洲在线精品视频 | 国产精品网在线观看 | 久久亚洲私人国产精品va | 国产中文字幕在线免费观看 | 91av看片 | 成年人免费在线看 | 免费一级特黄录像 | 成人九九视频 | 国产精品一区二区三区在线播放 | 欧美激情综合网 | 丝袜制服综合网 | 国产福利a | 中文字幕日本特黄aa毛片 | 一级国产视频 | 午夜视频不卡 | 日韩电影中文字幕 | 深爱激情婷婷网 | 天天综合网在线观看 | 欧美一区,二区 | 欧美日韩二三区 | 99视频免费 | 高潮久久久 | 成年人在线免费看视频 | 九九九视频精品 | 久久久黄视频 | 欧美福利在线播放 | 亚洲免费在线观看视频 | 亚洲精品男人的天堂 | 不卡的av在线| 亚洲第一区在线观看 | 人人澡人人舔 | 韩国三级在线一区 | 干av在线 | 欧美91片| 天天玩夜夜操 | 久草在线资源视频 | 精品久久久99 | 五月在线视频 | 亚洲精品在线视频 | 久草国产视频 | 亚洲精品日韩一区二区电影 | 欧美日韩在线观看不卡 | 国产精品综合久久久 | 久久精品国产精品亚洲精品 | 一区二区中文字幕在线观看 | 久精品在线观看 | 国产成人精品一区二区三区在线 | 一区二区中文字幕在线播放 | 久草观看视频 | 人交video另类hd | www.精选视频.com | 亚洲黄色免费观看 | 国产一级免费视频 | 亚洲国产精品女人久久久 | 国产精品国产三级在线专区 | 午夜久草 | 五月天狠狠操 | 日韩色av色资源 | 日韩大陆欧美高清视频区 | 亚洲黄色av网址 | 免费亚洲黄色 | av电影中文字幕 | 国产69精品久久99的直播节目 | 日本中文字幕在线看 | 久草视频在线资源站 | 精品影院一区二区久久久 | 91一区一区三区 | 日日噜噜噜噜夜夜爽亚洲精品 | a视频在线观看 | 正在播放国产精品 | 美女网站在线播放 | 久久电影国产免费久久电影 | 在线黄网站 | 欧洲亚洲精品 | 中文字幕乱码一区二区 | 97成人超碰 | 免费看污污视频的网站 | 91激情在线视频 | 精品国产aⅴ麻豆 | 亚洲丝袜一区 | 久草精品视频在线观看 | 国产黄色视| 国产精品6999成人免费视频 | a在线免费| 日韩精品免费一区二区 | 中文字幕免费成人 | 久久夜色精品亚洲噜噜国4 午夜视频在线观看欧美 | 免费日韩电影 | 综合久久久久久久久 | 不卡av电影在线 | 97精品久久人人爽人人爽 | 夜夜躁日日躁 | 日韩二区三区在线 | 黄色资源在线 | 亚洲综合色丁香婷婷六月图片 | 久久精品一二三区 | 中文字幕亚洲精品日韩 | 久久九九网站 | 成人九九视频 | 国产在线观看高清视频 | 黄色软件视频网站 | 99国产精品久久久久老师 | 91porny九色91啦中文 | 日韩黄色一区 | 亚洲色综合 | 精品久久免费看 | 午夜精品成人一区二区三区 | 亚洲精品视频www | 亚洲精品在线二区 | 久久久久久久精 | 亚洲jizzjizz日本少妇 | 99久久国产免费,99久久国产免费大片 | 欧美精品成人在线 | 国产一二三区av | 国产一级免费视频 | 欧洲在线免费视频 | 成人av播放| 8x成人免费视频 | 亚洲国产黄色 | 在线三级中文 | 99精品在线视频观看 | 国产成人三级在线观看 | 久久97超碰 | 国产精品久久精品国产 | 欧美另类美少妇69xxxx | 久草视频中文 | 欧美日韩综合在线观看 | 国产精品视频一二三 | 久久99视频免费观看 | 成人在线观看影院 | 免费高清国产 | 日韩高清黄色 | 黄色aa久久| 国产一区二区中文字幕 | 欧美日韩性视频 | 最新av网址在线观看 | 国模精品在线 | 综合激情网... | 欧美一级黄色视屏 | 狠狠操精品 | 美女网站色在线观看 | 欧美国产日韩久久 | 天天色天天| 欧美在线视频不卡 | 国产精品99蜜臀久久不卡二区 | 久久久久久国产一区二区三区 | 中文字幕人成乱码在线观看 | 一本一本久久a久久精品牛牛影视 | 国产成人精品一区二区三区网站观看 | 国产一区精品在线 | 精品国产伦一区二区三区 | 黄色国产区 | 国产精品久久久久久久久软件 | 在线播放你懂 | 99国产一区二区三精品乱码 | 性色va | 久久97精品 | 99精品视频在线观看免费 | 亚洲人片在线观看 | 亚洲欧美成人在线 | 久草视频中文在线 | 日韩二区在线播放 | 字幕网av | 久久精品国产亚洲 | 激情欧美一区二区三区免费看 | 日韩av综合网站 | 亚洲精品国产第一综合99久久 | 日韩女同一区二区三区在线观看 | av电影中文| 欧美一级片在线观看视频 | 99中文字幕在线观看 | 亚洲人成在线电影 | 国产精品美女久久久网av | 日韩免费视频在线观看 | 四虎影视8848dvd| 亚洲精品久久激情国产片 | 日韩欧美亚州 | 91高清在线 | 成年人在线免费视频观看 | 91爱爱网址 | 精品日韩中文字幕 | 久草精品视频 | 久久黄色免费观看 | 国产福利91精品一区 | 久久久久久免费毛片精品 | av免费播放 | 一区二区 精品 | 欧美一区二区三区在线看 | 91亚洲精品国偷拍 | 91精品国产一区二区三区 | 国产一区不卡在线 | 国产精品久久久久久久久久东京 | 91系列在线| 日日夜夜免费精品 | 国产69熟| 国产精品成人aaaaa网站 | av中文字幕剧情 | 最近中文字幕完整高清 | 中文伊人 | 一区二区三区 中文字幕 | 久久国产精品一区二区 | 欧美aa级| 丁香六月婷婷开心 | 在线黄色免费av | 国产艹b视频| 日韩视频免费观看高清完整版在线 | 99久久精品免费视频 | 免费看成人片 | 91丨九色丨国产丨porny精品 | 久久av黄色 | 日韩高清 一区 | 色综合五月 | www.久久com| 天天综合网 天天 | 在线观看av网 | 国产成人精品一区二区在线观看 | 丁香五月缴情综合网 | 日韩欧美视频在线观看免费 | 国产精品免费观看网站 | 国产亚洲午夜高清国产拍精品 | 日韩经典一区二区三区 | 色播激情五月 | 8x8x在线观看视频 | 国产高清日韩欧美 | 日韩专区中文字幕 | 一级黄色免费网站 | 在线免费观看成人 | 成人免费xxxxxx视频 | 久久99精品久久久久蜜臀 | 久久综合久久久久88 | 久久国产精彩视频 | 久久国产精品一国产精品 | 91在线免费视频观看 | 国产成人黄色 | 成 人 黄 色 片 在线播放 | 日韩.com| 成人在线观看资源 | 欧美黑吊大战白妞欧美 | 久久婷婷视频 | a电影在线观看 | 特级西西人体444是什么意思 | 99久久精品免费视频 | 日本精品视频在线观看 | 久久草草热国产精品直播 | 欧美成人日韩 | 蜜臀aⅴ国产精品久久久国产 | 国产免费观看久久 | 国产精品美女久久久久久久 | 欧美久久久久久久久久久 | 在线观看亚洲成人 | 久久99婷婷 | 成片人卡1卡2卡3手机免费看 | 亚洲撸撸 | 久久看片网 | 91av免费观看 | 亚洲精品福利在线 | 国产精品久一 | 国产爽视频 | 欧美综合在线视频 | 久久69精品久久久久久久电影好 | 在线观看国产麻豆 | 久久美女电影 | 午夜精品久久久久久久99婷婷 | 精品国产一区二区三区男人吃奶 | 国产在线不卡 | 亚洲国产精品激情在线观看 | 在线播放日韩av | 中文字幕高清有码 | 日韩精品视频免费专区在线播放 | 欧美激情另类文学 | 久久国产精品一区二区三区 | 日韩欧美有码在线 | av免费福利 | 美女亚洲精品 | 波多野结衣理论片 | 色综合久久久久久久久五月 | 中文字幕免费高清 | 免费视频91蜜桃 | 又黄又爽又无遮挡免费的网站 | 欧美成人性战久久 | 免费国产在线精品 | 男女拍拍免费视频 | 国产精品九九九九九九 | 黄色特级一级片 | 久久老司机精品视频 | 亚洲狠狠丁香婷婷综合久久久 | 亚洲综合最新在线 | 免费成人在线观看视频 | 国产一区二区日本 | 久久一区二 | 天天综合天天综合 | 国产va在线观看免费 | 国产小视频国产精品 | 久久99免费 | 国产精品久久免费看 | 在线视频观看你懂的 | 免费高清无人区完整版 | 日韩av影视 | 一级黄色免费网站 | 视频一区二区在线 | 亚洲精品国产精品99久久 | 一级理论片在线观看 | 国产三级精品三级在线观看 | 天天亚洲综合 | 永久免费毛片 | 黄色小说网站在线 | 久久黄色免费视频 | 精品国产一二三 | 亚洲成免费| 日韩一区二区三区观看 | 色资源网在线观看 | 成人a毛片 | av软件在线观看 | 国产中文在线视频 | 久久国产精品成人免费浪潮 | 日韩中文字幕视频在线观看 | 一区二区三区在线观看免费 | 精品国产乱码久久久久久浪潮 | 99久久精品国产系列 | 日韩av网页| 99精品一区二区三区 | av在线色 | 欧美日韩在线看 | 天天摸夜夜添 | 久久手机在线视频 | 国产99一区 | 日韩精品在线免费播放 | 国产中文欧美日韩在线 | 日韩艹 | 亚洲精品乱码久久久久久9色 | 超碰人人99 | 亚洲夜夜网| 黄色片网站大全 | 午夜精品福利一区二区 | 日韩一区二区久久 | 亚洲午夜精 | 四虎天堂 | 久久手机免费观看 | 西西www4444大胆在线 | 日韩欧美v| 日韩极品在线 | 欧美一级片在线播放 | 久久免费视频在线观看30 | 夜夜狠狠 | 色综合久久久久久久 | 亚洲专区在线播放 | 久久久久免费精品国产小说色大师 | 国产在线中文 | 国产高清网站 | 狠狠色丁香 | 最新真实国产在线视频 | www视频在线播放 | 在线一区电影 | 伊人影院得得 | 久久96 | 成人av电影在线观看 | 91传媒在线看 | 在线免费观看麻豆视频 | 黄色成年网站 | 区一区二区三在线观看 | 能在线看的av | 日韩网站在线免费观看 | 免费视频 你懂的 | 久久久国产一区二区三区 | 啪啪动态视频 | 国产精品一区二区久久国产 | 日日操网站 | 国产69精品久久99不卡的观看体验 | av看片在线观看 | 中文乱码视频在线观看 | 在线你懂的视频 | 激情久久五月 | 成人aⅴ视频 | 亚洲丝袜一区二区 | 精品主播网红福利资源观看 | 日本三级香港三级人妇99 | 久久av在线播放 | 麻豆精品视频在线观看免费 | 东方av在线免费观看 | 丁香婷婷综合五月 | 久久久久在线视频 | 日韩欧美一区二区在线观看 | 在线黄色免费av | 国内精品久久久久国产 | 五月天久久狠狠 | 久久国产精品一区二区三区 | 国产精品电影在线 | 久久国内精品99久久6app | 国产日韩在线观看一区 | 91精品国产网站 | 激情婷婷综合网 | 狠狠干夜夜操 | 97超碰人人澡 | 日韩免费在线观看视频 | 亚洲女欲精品久久久久久久18 | 国产高清在线免费视频 | 高清在线一区 | 97天堂 | www.五月天色| 在线视频 国产 日韩 | 精品自拍sae8—视频 | 香蕉91视频 | 91视频高清完整版 | 91亚洲精| 国产精品电影一区二区 | 麻豆视频国产精品 | av黄色免费网站 | 日日摸日日添日日躁av | 日韩精品亚洲专区在线观看 | 国产福利在线不卡 | 99久久久久久久久 | 精品一区欧美 | 日韩中文字幕免费看 | 婷婷射五月| 免费一级特黄毛大片 | 97超级碰碰碰视频在线观看 | 久久久久久久久久电影 | 久久久黄色av| 成人在线视频你懂的 | 久草青青在线观看 | 91在线你懂的 | 国产一区免费观看 | 91日韩免费| 久草在线费播放视频 | 国内精品久久久久影院优 | 欧亚日韩精品一区二区在线 | 亚洲永久在线 | 欧美污污网站 | 九九久久影院 | 国产一区自拍视频 | 精品国产免费一区二区三区五区 | 亚洲精品国产拍在线 | 日韩激情在线 | 成人av网站在线播放 | 久久久久久久久久免费 | 韩国av在线| 国产一区二区在线播放 | 日日躁你夜夜躁你av蜜 | 中文字幕中文字幕中文字幕 | 在线观看午夜 | 成人在线免费观看网站 | 国产精品精品久久久久久 | 免费在线激情电影 | 一本色道久久综合亚洲二区三区 | 国产精品免费久久久久久久久久中文 | 一区二区三区精品在线视频 | 日韩欧美视频在线免费观看 | 国产电影黄色av | www.av免费观看 | 欧美一性一交一乱 | 中文字幕日韩有码 | 在线观看视频亚洲 | 在线观看一级 | 久久免费国产精品 | 国产又黄又爽无遮挡 | 国产精品人成电影在线观看 | 国产精品第二页 | 亚洲欧美日韩一二三区 | 91看片一区二区三区 | 精品一区 在线 | 亚洲少妇xxxx | 在线观看免费高清视频大全追剧 | 男女啪啪视屏 | 中文字幕综合在线 | 五月香视频在线观看 | 欧美日韩午夜在线 | 激情中文在线 | 五月激情丁香婷婷 | 成年人网站免费在线观看 | 嫩小bbbb摸bbb摸bbb | 美女网站免费福利视频 | 国产成人亚洲在线电影 | 丁香五婷 | 91精品国产综合久久婷婷香蕉 | 精品国产乱码久久久久久1区二区 | 亚洲丝袜一区二区 | 黄色国产大片 | 成人午夜剧场在线观看 | 久久精品视频网 | 免费在线激情电影 | 中文字幕在线播放av | 久久综合亚洲鲁鲁五月久久 | 亚洲少妇激情 | av观看久久久 | 欧美乱大交| 国产真实在线 | 91在线视频导航 | av不卡免费在线观看 | 国产国语在线 | 日本一区二区不卡高清 | 免费在线观看日韩 | 亚洲国产精品va在线看黑人动漫 | 亚洲成人av电影在线 | 最近最新中文字幕视频 | 99精品欧美一区二区 | 国产午夜一区 | 一级免费看 | 欧美精品久久久久久久久久丰满 | 色网av| 婷婷色5月| 欧美日韩激情视频8区 | 又黄又刺激的视频 | 久久精品国产免费看久久精品 | www色综合 | 一区 二区电影免费在线观看 | 中文字幕在线视频一区二区 | 在线成人国产 | 在线观看免费av网站 | 中文字幕丝袜一区二区 | 探花视频免费观看高清视频 | 国产免费又爽又刺激在线观看 | 99精品亚洲 | a在线观看视频 | 四虎影视久久久 | 深爱婷婷 | 国产黄色片一级 | 五月天久久综合网 | 国内毛片毛片 | 国产精品免费观看国产网曝瓜 | 五月天激情综合 | a黄在线观看 | 色婷婷av一区二 | 日日麻批40分钟视频免费观看 | 久久成人国产精品入口 | 黄色网www | 91大神精品视频在线观看 | 色网av | 国产成人一区二区精品非洲 | av在线官网 | 91最新在线观看 | 久久国内视频 | 色婷婷av国产精品 | 久久久久国产精品一区 | a级成人毛片 | 日韩国产精品一区 | 九九九热视频 | 久久五月婷婷丁香 | 欧美色久 | 九九免费在线观看视频 | 久久精品网站免费观看 | 欧美精品中文 | 精品xxx| 少妇bbb好爽 | 国产电影一区二区三区四区 | 九九热只有精品 | 伊甸园av在线 | 久久看片网站 | 综合国产在线观看 | 激情综合中文娱乐网 | 国产91九色视频 | 亚洲激情六月 | 久久免费激情视频 | 久草青青在线观看 | 性色av一区二区三区在线观看 | 久久在线视频精品 | 青青河边草免费视频 | 国产精品成人a免费观看 | 欧美aa级 | 在线视频免费观看 | 尤物一区二区三区 | 国产视频69 | 国产一区二区成人 | 欧美大jb| 午夜美女wwww | www.久久色| av电影免费在线播放 | 少妇视频在线播放 | 欧美a级片免费看 | 色综合亚洲精品激情狠狠 | 亚洲成人精品影院 | 日韩在线免费电影 | 亚洲综合五月天 | 国产大片黄色 | 精品久久久久久久久中文字幕 | 欧美黑人巨大xxxxx | 国产精品手机视频 | 在线观看免费国产小视频 | 天天干国产 | 亚洲精品乱码 | 超薄丝袜一二三区 | 亚洲国产影院 | 99久久久国产精品免费99 | 国产视频精选在线 | 亚洲成av人片在线观看香蕉 | 日本色小说视频 | 欧美性极品xxxx做受 | www.888av | 欧美a级在线免费观看 | 国产亚洲精品成人av久久影院 | 成人午夜精品久久久久久久3d | 国产福利精品视频 | 综合久色 | 99视频这里有精品 | 国产玖玖在线 | 天天干天天拍天天操天天拍 | 91丨九色丨蝌蚪丨对白 | 欧美日韩免费一区二区 | 一级片免费观看视频 | 婷婷丁香综合 | av在线播放中文字幕 | 国际精品网 | 免费看国产a | 97超碰精品| 日韩久久精品一区二区三区 | a级黄色片视频 | 中文在线8资源库 | 夜夜躁日日躁狠狠久久av | 国产精品一区二区免费视频 | 久久久蜜桃一区二区 | 激情欧美日韩一区二区 | 2021久久| 在线天堂中文在线资源网 | 99精品国产成人一区二区 | 国产成人三级 | 九九九毛片 | www.色婷婷 | 国产精品综合在线观看 | 人人超碰免费 | 成年一级片 | 久久天天躁狠狠躁亚洲综合公司 | 国产资源网 | 亚洲爱爱视频 | 久久午夜精品视频 | 丁香婷婷激情网 | 久久国产精品久久w女人spa | 国产第页 | 国产一区二区三区网站 | 成人在线免费视频 | 91精品国产99久久久久久久 | 国产精品高潮在线观看 | 五月综合激情 | 国产第一页在线播放 | 国产在线国偷精品产拍 | 精品福利在线观看 | 亚洲色图27p | 日韩一区二区三区在线观看 | 亚洲动漫在线观看 | 国产麻豆精品传媒av国产下载 | 国产69精品久久久久久 | 五月婷婷色播 | 久久久午夜剧场 | 九九免费在线观看 | 一区二区不卡高清 | 色网站在线免费 |