久久福利_99r_国产日韩在线视频_直接看av的网站_中文欧美日韩_久久一

您的位置:首頁技術文章
文章詳情頁

如何使用Java模擬退火算法優化Hash函數

瀏覽:223日期:2022-08-10 13:54:44
目錄一、背景二、放棄 hash 函數三、優化 hash 函數3.1、評價函數3.2、訓練策略3.3、ForkJoin 框架3.4、效果一、背景

現有個處理股票行情消息的系統,其架構如下:

如何使用Java模擬退火算法優化Hash函數

由于數據量巨大,系統中啟動了 15 個線程來消費行情消息。消息分配的策略較為簡單:對 symbol 的 hashCode 取模,將消息分配給其中一個線程進行處理。 經過驗證,每個線程分配到的 symbol 數量較為均勻,于是系統愉快地上線了。

運行一段時間后,突然收到了系統的告警,但此時并非消息峰值時間段。經過排查后,發現問題出現在 hash 函數上:

如何使用Java模擬退火算法優化Hash函數

雖然每個線程被分配到的 symbol 數量較為均衡,但是部分熱門 symbol 的報價消息量會更多,如果熱門 symbol 集中到特定線程上,就會造成線程負載不均衡,使得系統整體的吞吐量大打折扣。

為提高系統的吞吐量,有必要消息分發邏輯進行一些改造,避免出現熱點線程。為此,系統需要記錄下某天內每個 symbol 的消息量,然后在第二天使用這些數據,對分發邏輯進行調整。具體的改造的方案可以分為兩種:

放棄使用 hash 函數 對 hash 函數進行優化二、放棄 hash 函數

問題可以抽象為:

將 5000 個非負整數分配至 15 個桶(bucket)中,并盡可能保證每個桶中的元素之和接近(每個桶中的元素個數無限制)。

每個整數元素可能的放置方法有 15 種,這個問題總共可能的解有 155000種,暴力求解的可能性微乎其微。作為工程問題,最優解不是必要的,可以退而求其次尋找一個可接受的次優解:

根據所有 symbol 的消息總數計算一個期望的分布均值(expectation)。將每個 symbol 的消息數按照 symbol 的順序進行排列,最后將這組數組劃分為 15 個區間,并且盡可能使得每個區間元素之和與 expection 接近。使用一個有序查找表記錄每個區間的首個 symbol,后續就可以按照這個表對數據進行劃分。

public class FindBestDistribution { static final int NUM_OF_SYMBOLS = 5000; static final int NUM_OF_BUCKETS = 15; public static void main(String[] args) {// 生成樣本IntStream ints = ThreadLocalRandom.current().ints(0, 1000);PrimitiveIterator.OfInt iterator = ints.iterator();Map<String,Integer> symbolAndCount = new TreeMap<>();for (int i=0; i<NUM_OF_SYMBOLS; i++) { symbolAndCount.put(Integer.toHexString(i).toUpperCase(), iterator.next());}// 按照 symbol 劃分每個桶的數量TreeMap<String, Integer> distribution = findBestDistribution(symbolAndCount);// 測試效果int[] buckets = new int[NUM_OF_BUCKETS];for (Map.Entry<String, Integer> entry : symbolAndCount.entrySet()) { Map.Entry<String, Integer> floor = distribution.floorEntry(entry.getKey()); int bucketIndex = floor == null ? 0 : floor.getValue(); buckets[bucketIndex] += entry.getValue();}System.out.printf('buckets: %sn', Arrays.toString(buckets)); } public static TreeMap<String, Integer> findBestDistribution(Map<String,Integer> symbolAndCount) {// 每個桶均勻分布的情況(最優情況)int avg = symbolAndCount.values().stream().mapToInt(Integer::intValue).sum() / NUM_OF_BUCKETS;// 嘗試將 symbol 放入不同的桶int bucketIdx = 0;int[] buckets = new int[NUM_OF_BUCKETS];String[] bulkheads = new String[NUM_OF_BUCKETS-1];for (Map.Entry<String, Integer> entry : symbolAndCount.entrySet()) { // 如果首個 symbol 數據量過大,則分配給其一個獨立的桶 int count = entry.getValue(); if (count / 2 > avg && bucketIdx == 0 && buckets[0] == 0) {buckets[bucketIdx] += count;continue; } // 評估將 symbol 放入桶后的效果 // 1. 如果桶中的數量更接近期望,則將其放入當前桶中 // 2. 如果桶中的數量更遠離期望,則將其放入下個桶中 double before = Math.abs(buckets[bucketIdx] - avg); double after = Math.abs(buckets[bucketIdx] + count - avg); if (after > before && bucketIdx < buckets.length - 1) {bulkheads[bucketIdx++] = entry.getKey(); } buckets[bucketIdx] += count;}System.out.printf('expectation: %dn', avg);System.out.printf('bulkheads: %sn', Arrays.toString(bulkheads));TreeMap<String,Integer> distribution = new TreeMap<>();for (int i=0; i<bulkheads.length; i++) { distribution.put(bulkheads[i], i+1);}return distribution; }}

該方法存在的問題:

分配策略并不是最優解,且無法對其分片效果進行直觀的評估。 當區間數量較多時,查找表本身可能成為一個潛在的性能瓶頸。 可能的組合受到 key 的順序限制,極大地限制了可能的解空間。三、優化 hash 函數

換個角度來看,造成分布不均勻的原因不是數據,而是 hash 函數本身。

項目中使用的 hash 函數是 JDK String 中的原生實現。經過查閱資料,發現該實現其實是 BKDRHash 的 seed = 31 的特殊情況。這樣意味著:通過調整 seed 的值,可以改變 hash 函數的特性并使其適配特定的數據分布。

int BKDRHash(char[] value, int seed) { int hash = 0; for (int i = 0; i < value.length; i++) {hash = hash * seed + value[i]; } return hash & 0x7fffffff;}

那么問題來了,應該如何評估某個 seed 的分布的優劣?

3.1、評價函數

一種可行的方法是計算每個 seed 對應的 bucket 分布的標準差,標準差越小則分布越均勻,則該 seed 越優。

然而這一做法只考慮了每個 bucket 與均值之間的誤差,無法量化不同 bucket 之間的誤差。為了能夠直觀的量化 bucket 之間分布差異的情況,考慮使用下面的評估函數:

ouble calculateDivergence(long[] bucket, long expectation) { long divergence = 0; for (int i=0; i<bucket.length; i++) {final long a = bucket[i];final long b = (a - expectation) * (a - expectation);for (int j=i+1; j<bucket.length; j++) { long c = (a - bucket[j]) * (a - bucket[j]); divergence += Math.max(b, c);} } return divergence; // the less the better}

該數值越小,則證明 seed 對應的分布越均勻,其對應的 hash 函數越優。

3.2、訓練策略

seed 是一個 32bit 的無符號整數,其取值范圍為 0 ~ 232-1。在 5000 個 symbol 的情況下,單線程嘗試遍歷所有 seed 的時間約為 25 小時。

通常情況下 symbol 的數量會超過 5000,因此實際的搜索時間會大于這個值。此外,受限于計算資源限制,無法進行大規模的并行搜索,因此窮舉法的耗時是不可接受的。

幸好本例并不要求最優解,可以引入啟發式搜索算法,加快訓練速度。由于本人在這方面并不熟悉,為了降低編程難度,最終選擇了模擬退火(simulated annealing)算法。它模擬固體退火過程的熱平衡問題與隨機搜索尋優問題的相似性來達到尋找全局最優或近似全局最優的目的。相較于最簡單的爬山法,模擬退火算法通以一定的概率接受較差的解,從而擴大搜索范圍,保證解近似最優。

/** * Basic framework of simulated annealing algorithm * @param <X> the solution of given problem */public abstract class SimulatedAnnealing<X> { protected final int numberOfIterations; // stopping condition for simulations protected final double coolingRate;// the percentage by which we reduce the temperature of the system protected final double initialTemperature; // the starting energy of the system protected final double minimumTemperature; // optional stopping condition protected final long simulationTime; // optional stopping condition protected final int detectionInterval; // optional stopping condition protected SimulatedAnnealing(int numberOfIterations, double coolingRate) {this(numberOfIterations, coolingRate, 10000000, 1, 0, 0); } protected SimulatedAnnealing(int numberOfIterations, double coolingRate, double initialTemperature, double minimumTemperature, long simulationTime, int detectionInterval) {this.numberOfIterations = numberOfIterations;this.coolingRate = coolingRate;this.initialTemperature = initialTemperature;this.minimumTemperature = minimumTemperature;this.simulationTime = simulationTime;this.detectionInterval = detectionInterval; } protected abstract double score(X currentSolution); protected abstract X neighbourSolution(X currentSolution); public X simulateAnnealing(X currentSolution) {final long startTime = System.currentTimeMillis();// Initialize searchingX bestSolution = currentSolution;double bestScore = score(bestSolution);double currentScore = bestScore;double t = initialTemperature;for (int i = 0; i < numberOfIterations; i++) { if (currentScore < bestScore) {// If the new solution is better, accept it unconditionallybestScore = currentScore;bestSolution = currentSolution; } else {// If the new solution is worse, calculate an acceptance probability for the worse solution// At high temperatures, the system is more likely to accept the solutions that are worseboolean rejectWorse = Math.exp((bestScore - currentScore) / t) < Math.random();if (rejectWorse || currentScore == bestScore) { currentSolution = neighbourSolution(currentSolution); currentScore = score(currentSolution);} } // Stop searching when the temperature is too low if ((t *= coolingRate) < minimumTemperature) {break; } // Stop searching when simulation time runs out if (simulationTime > 0 && (i+1) % detectionInterval == 0) {if (System.currentTimeMillis() - startTime > simulationTime) break; }}return bestSolution; }}/** * Search best hash seed for given key distribution and number of buckets with simulated annealing algorithm */@Datapublic class SimulatedAnnealingHashing extends SimulatedAnnealing<HashingSolution> { private static final int DISTRIBUTION_BATCH = 100; static final int SEARCH_BATCH = 200; private final int[] hashCodes = new int[SEARCH_BATCH]; private final long[][] buckets = new long[SEARCH_BATCH][]; @Data public class HashingSolution {private final int begin, range; // the begin and range for searchingprivate int bestSeed; // the best seed found in this searchprivate long bestScore; // the score corresponding to bestSeedprivate long calculateDivergence(long[] bucket) { long divergence = 0; for (int i=0; i<bucket.length; i++) {final long a = bucket[i];final long b = (a - expectation) * (a - expectation);for (int j=i+1; j<bucket.length; j++) { long c = (a - bucket[j]) * (a - bucket[j]); divergence += Math.max(b, c);} } return divergence; // the less the better}private HashingSolution solve() { if (range != hashCodes.length) {throw new IllegalStateException(); } for (int i=0; i<range; i++) {Arrays.fill(buckets[i], hashCodes[i] = 0); } for (KeyDistribution[] bucket : distributions) {for (KeyDistribution distribution : bucket) { Hashing.BKDRHash(distribution.getKey(), begin, hashCodes); for (int k = 0; k< hashCodes.length; k++) {int n = hashCodes[k] % buckets[k].length;buckets[k][n] += distribution.getCount(); }} } int best = -1; long bestScore = Integer.MAX_VALUE; for (int i = 0; i< buckets.length; i++) {long score = calculateDivergence(buckets[i]);if (i == 0 || score < bestScore) { bestScore = score; best = i;} } if (best < 0) {throw new IllegalStateException(); } this.bestScore = bestScore; this.bestSeed = begin + best; return this;}@Overridepublic String toString() { return String.format('(seed:%d, score:%d)', bestSeed, bestScore);} } private final KeyDistribution[][] distributions; // key and its count(2-dimensional array for better performance) private final long expectation; // the expectation count of each bucket private final int searchOutset; private int searchMin, searchMax; /** * SimulatedAnnealingHashing Prototype * @param keyAndCounts keys for hashing and count for each key * @param numOfBuckets number of buckets */ public SimulatedAnnealingHashing(Map<String, Integer> keyAndCounts, int numOfBuckets) {super(100000000, .9999);distributions = buildDistribution(keyAndCounts);long sum = 0;for (KeyDistribution[] batch : distributions) { for (KeyDistribution distribution : batch) {sum += distribution.getCount(); }}this.expectation = sum / numOfBuckets;this.searchOutset = 0;for (int i = 0; i< buckets.length; i++) { buckets[i] = new long[numOfBuckets];} } /** * SimulatedAnnealingHashing Derivative * @param prototype prototype simulation * @param searchOutset the outset for searching * @param simulationTime the expect time consuming for simulation */ private SimulatedAnnealingHashing(SimulatedAnnealingHashing prototype, int searchOutset, long simulationTime) {super(prototype.numberOfIterations, prototype.coolingRate, prototype.initialTemperature, prototype.minimumTemperature,simulationTime, 10000);distributions = prototype.distributions;expectation = prototype.expectation;for (int i = 0; i< buckets.length; i++) { buckets[i] = new long[prototype.buckets[i].length];}this.searchOutset = searchOutset;this.searchMax = searchMin = searchOutset; } @Override public String toString() {return String.format('expectation: %d, outset:%d, search(min:%d, max:%d)', expectation, searchOutset, searchMin, searchMax); } private KeyDistribution[][] buildDistribution(Map<String, Integer> symbolCounts) {int bucketNum = symbolCounts.size() / DISTRIBUTION_BATCH + Integer.signum(symbolCounts.size() % DISTRIBUTION_BATCH);KeyDistribution[][] distributions = new KeyDistribution[bucketNum][];int bucketIndex = 0;List<KeyDistribution> batch = new ArrayList<>(DISTRIBUTION_BATCH);for (Map.Entry<String, Integer> entry : symbolCounts.entrySet()) { batch.add(new KeyDistribution(entry.getKey().toCharArray(), entry.getValue())); if (batch.size() == DISTRIBUTION_BATCH) {distributions[bucketIndex++] = batch.toArray(new KeyDistribution[0]);batch.clear(); }}if (batch.size() > 0) { distributions[bucketIndex] = batch.toArray(new KeyDistribution[0]); batch.clear();}return distributions; } @Override protected double score(HashingSolution currentSolution) {return currentSolution.solve().bestScore; } @Override protected HashingSolution neighbourSolution(HashingSolution currentSolution) {// The default range of neighbourhood is [-100, 100]int rand = ThreadLocalRandom.current().nextInt(-100, 101);int next = currentSolution.begin + rand;searchMin = Math.min(next, searchMin);searchMax = Math.max(next, searchMax);return new HashingSolution(next, currentSolution.range); } public HashingSolution solve() {searchMin = searchMax = searchOutset;HashingSolution initialSolution = new HashingSolution(searchOutset, SEARCH_BATCH);return simulateAnnealing(initialSolution); } public SimulatedAnnealingHashing derive(int searchOutset, long simulationTime) {return new SimulatedAnnealingHashing(this, searchOutset, simulationTime); }}3.3、ForkJoin 框架

為了達到更好的搜索效果,可以將整個搜索區域遞歸地劃分為兩兩相鄰的區域,然后在這些區域上執行并發的搜索,并遞歸地合并相鄰區域的搜索結果。

使用 JDK 提供的 ForkJoinPool 與 RecursiveTask 能很好地完成以上任務。

@Data@Slf4jpublic class HashingSeedCalculator { /** * Recursive search task */ private class HashingSeedCalculatorSearchTask extends RecursiveTask<HashingSolution> {private SimulatedAnnealingHashing simulation;private final int level;private final int center, range;private HashingSeedCalculatorSearchTask() { this.center = 0; this.range = Integer.MAX_VALUE / SimulatedAnnealingHashing.SEARCH_BATCH; this.level = traversalDepth; this.simulation = hashingSimulation;}private HashingSeedCalculatorSearchTask(HashingSeedCalculatorSearchTask parent, int center, int range) { this.center = center; this.range = range; this.level = parent.level - 1; this.simulation = parent.simulation;}@Overrideprotected HashingSolution compute() { if (level == 0) {long actualCenter = center * SimulatedAnnealingHashing.SEARCH_BATCH;log.info('Searching around center {}', actualCenter);HashingSolution solution = simulation.derive(center, perShardRunningMills).solve();log.info('Searching around center {} found {}', actualCenter, solution);return solution; } else {int halfRange = range / 2;int leftCenter = center - halfRange, rightCenter = center + halfRange;ForkJoinTask<HashingSolution> leftTask = new HashingSeedCalculatorSearchTask(this, leftCenter, halfRange).fork();ForkJoinTask<HashingSolution> rightTask = new HashingSeedCalculatorSearchTask(this, rightCenter, halfRange).fork();HashingSolution left = leftTask.join();HashingSolution right = rightTask.join();return left.getBestScore() < right.getBestScore() ? left : right; }} } private final int poolParallelism; private final int traversalDepth; private final long perShardRunningMills; private final SimulatedAnnealingHashing hashingSimulation; /** * HashingSeedCalculator * @param numberOfShards the shard of the whole search range [Integer.MIN_VALUE, Integer.MAX_VALUE] * @param totalRunningHours the expect total time consuming for searching * @param symbolCounts the key and it`s distribution * @param numOfBuckets the number of buckets */ public HashingSeedCalculator(int numberOfShards, int totalRunningHours, Map<String, Integer> symbolCounts, int numOfBuckets) {int n = (int) (Math.log(numberOfShards) / Math.log(2));if (Math.pow(2, n) != numberOfShards) { throw new IllegalArgumentException();}this.traversalDepth = n;this.poolParallelism = Math.max(ForkJoinPool.getCommonPoolParallelism() / 3 * 2, 1); // conservative estimation for parallelismthis.perShardRunningMills = TimeUnit.HOURS.toMillis(totalRunningHours * poolParallelism) / numberOfShards;this.hashingSimulation = new SimulatedAnnealingHashing(symbolCounts, numOfBuckets); } @Override public String toString() {int numberOfShards = (int) Math.pow(2, traversalDepth);int totalRunningHours = (int) TimeUnit.MILLISECONDS.toHours(perShardRunningMills * numberOfShards) / poolParallelism;return 'HashingSeedCalculator(' +'numberOfShards: ' + numberOfShards +', perShardRunningMinutes: ' + TimeUnit.MILLISECONDS.toMinutes(perShardRunningMills) +', totalRunningHours: ' + totalRunningHours +', poolParallelism: ' + poolParallelism +', traversalDepth: ' + traversalDepth + ')'; } public synchronized HashingSolution searchBestSeed() {long now = System.currentTimeMillis();log.info('SearchBestSeed start');ForkJoinTask<HashingSolution> root = new HashingSeedCalculatorSearchTask().fork();HashingSolution initSolution = hashingSimulation.derive(0, perShardRunningMills).solve();HashingSolution bestSolution = root.join();log.info('Found init solution {}', initSolution);log.info('Found best solution {}', bestSolution);if (initSolution.getBestScore() < bestSolution.getBestScore()) { bestSolution = initSolution;}long cost = System.currentTimeMillis() - now;log.info('SearchBestSeed finish (cost:{}ms)', cost);return bestSolution; }}3.4、效果

將改造后的代碼部署到測試環境后,某日訓練日志:

12:49:15.227 85172866 INFO hash.HashingSeedCalculator - Found init solution (seed:15231, score:930685828341164)12:49:15.227 85172866 INFO hash.HashingSeedCalculator - Found best solution (seed:362333, score:793386389726926)12:49:15.227 85172866 INFO hash.HashingSeedCalculator - SearchBestSeed finish (cost:10154898ms)12:49:15.227 85172866 INFO hash.TrainingService -Training result: (seed:362333, score:793386389726926)Buckets: 15Expectation: 44045697Result of Hashing.HashCode(seed=362333): 21327108 [42512742, 40479608, 43915771, 47211553, 45354264, 43209190, 43196570, 44725786, 41999747, 46450288, 46079231, 45116615, 44004021, 43896194, 42533877]Result of Hashing.HashCode(seed=31): 66929172 [39723630, 48721463, 43365391, 46301448, 43931616, 44678194, 39064877, 45922454, 43171141, 40715060, 33964547, 49709090, 58869949, 34964729, 47581868]

當晚使用 BKDRHash(seed=31) 對新的交易日數據的進行分片:

04:00:59.001 partition messages per minute [45171, 68641, 62001, 80016, 55977, 61916, 55102, 49322, 55982, 57081, 51100, 70437, 135992, 37823, 58552] , messages total [39654953, 48666261, 43310578, 46146841, 43834832, 44577454, 38990331, 45871075, 43106710, 40600708, 33781629, 49752592, 58584246, 34928991, 47545369]

當晚使用 BKDRHash(seed=362333) 對新的交易日數據的進行分片:

04:00:59.001 partition messages per minute [62424, 82048, 64184, 47000, 57206, 69439, 64430, 60096, 46986, 58182, 54557, 41523, 64310, 72402, 100326] , messages total [44985772, 48329212, 39995385, 43675702, 45216341, 45524616, 41335804, 44917938, 44605376, 44054821, 43371892, 42068637, 44000817, 42617562, 44652695]

對比日志發現 hash 經過優化后,分區的均勻程度有了顯著的上升,并且熱點分片也被消除了,基本達到當初設想的優化效果。

以上就是如何使用Java模擬退火算法優化Hash函數的詳細內容,更多關于Java 模擬退火算法優化Hash的資料請關注好吧啦網其它相關文章!

標簽: Java
相關文章:
主站蜘蛛池模板: 国产最新视频 | 国产精品自产拍在线观看 | 国产中文一区 | 午夜视频网址 | 人人草视频在线观看 | 国产成人精品免费 | 四虎中文字幕 | 免看一级一片 | 手机看片369 | 天天操天天添 | 精品久久久久一区二区国产 | 奇米影视7777 | 欧美日韩国产精品一区二区 | 一级免费片 | 日韩激情视频一区 | 成av在线| 亚洲人人舔人人 | 国产九九九 | 黄色片视频在线观看 | 成人爽a毛片一区二区免费 亚洲自拍偷拍精品 | 色播99 | 成人a在线视频免费观看 | 国产成人综合av | 日本视频免费高清一本18 | 在线视频中文字幕 | 久久亚洲综合 | 日韩一区二区三区精品 | 成人午夜精品久久久久久久蜜臀 | 精品国产乱码一区二区三区 | 日韩精品视频在线播放 | 国产免费一区二区三区最新不卡 | 国产精品网站在线观看 | 久久精品2 | 日本久久精品视频 | 国产精品成人品 | 日韩欧美视频 | 91高清免费看 | 欧美一区二区三区在线 | 国产视频h | 二区影院 | 欧美日韩一区二区三区不卡视频 | 一区二区三区四区在线 | 国产激情免费 | 97国产一区二区精品久久呦 | 成人中文网 | www.亚洲一区二区 | 国产亚洲精品v | 青青草一区 | 台湾佬亚洲色图 | 欧美久久久久久久久久久久久久 | 久久精品一 | 久久久国产一区二区三区 | 一区二区三区四区免费观看 | 日本欧美在线 | 成人久久久 | 蜜桃视频在线播放 | 亚洲精品中文字幕中文字幕 | 久久国产精品视频 | 999国内精品永久免费视频 | 国产精品一区二 | 欧洲精品乱码久久久久蜜桃 | 久久久婷 | 欧美视频二区 | 久久精品二区 | 日本一区二区视频 | 99免费视频 | 亚洲欧美日韩一区 | 不用播放器的av | 婷婷丁香激情网 | 精品国产乱码久久久久久久软件 | 成人在线视频一区二区 | 久久精品欧美 | 亚洲欧美韩国 | 国产视频一视频二 | 夜夜久久 | 日韩成人一区 | 国产成人免费视频网站视频社区 | 日韩福利片 | 一区二区三区亚洲 | 国产一区二区在线看 | www一区二区 | 黄色一级免费看 | 国内外成人在线视频 | 波多野结衣一区二区三区高清 | 国产依人在线 | 国产视频中文字幕 | 三级色黄 | 日韩精品视频免费在线观看 | 日韩a∨ | 国产成人精品免高潮在线观看 | 亚洲精品成人在线 | 九九免费在线观看 | 日韩欧美一级在线 | 午夜免费视频福利 | 美国黄色毛片女人性生活片 | 久久精品国产99国产精品 | 日产精品久久 | 能在线观看的黄色网址 | 99精品99| 天天艹久久 | 久久久久久a女人 | 亚洲精品久久久久久一区二区 | 成人免费毛片aaaaaa片 | 天天色天天色 | 国产精品夜夜 | 中文字幕一页二页 | 蜜桃视频一区 | 免费av一区二区三区 | 91天堂在线观看 | h网站在线观看 | 国产精品视频在线观看 | 国产精久久久久久久妇剪断 | av久草| 国产精品久久久久久久久福交 | 亚洲 欧美 另类 综合 偷拍 | 亚洲国产精品成人综合色在线婷婷 | 伊人激情av一区二区三区 | 99re视频在线观看 | 在线视频亚洲 | 成人亚洲| 福利网址 | 2019天天干夜夜操 | www.五月婷 | www.久久久久久久 | 激情一区| 久久免费视频观看 | av中文在线 | 久久一区视频 | 国产精品不卡一区 | 综合久久国产九一剧情麻豆 | 91久久精品一区二区二区 | 国产成人在线免费观看视频 | 精品久久久久香蕉网 | 日韩毛片 | 在线观看国产小视频 | 亚洲精品7777xxxx青睐 | 亚洲天堂影视 | 亚洲精品日韩综合观看成人91 | www.日韩 | 国产一区二区三区四区在线观看 | 精品国产鲁一鲁一区二区三区 | 国产精品欧美一区二区 | 日韩欧美国产精品 | 国产欧美日韩一区 | 国产乱码精品一区二区三区忘忧草 | 国产精品视频导航 | 欧美不卡 | 毛片网站大全 | 国产精品国产精品国产专区不卡 | 一区二区三区国产 | 色婷婷国产精品 | 午夜社区 | 精品九九 | 国产成人精品一区二区三区视频 | 欧美综合成人网 | 午夜国产一级片 | 96自拍视频 | 亚洲免费视频网址 | 午夜视频网站 | 日韩在线一区二区 | 久久人人爽人人爽 | 国产中文在线 | 亚洲一区在线免费观看 | 特级丰满少妇一级aaaa爱毛片 | 日韩在线不卡 | 99re视频在线观看 | 午夜日韩在线观看 | 久久六月| 精品在线一区 | 蜜桃comaaa| 狠狠操狠狠操 | 日韩成人一区二区 | 欧美一级在线观看视频 | 欧美性猛交一区二区三区精品 | 中文字幕在线欧美 | 国产一区二| 欧美一区二区日韩 | 在线播放亚洲 | 日本午夜网 | 欧美日韩不卡合集视频 | 亚洲精品色 | 麻豆精品国产传媒 | 国产一区精品视频 | 天天插天天操 | 亚洲精品国产电影 | 国产成人精品一区二 | 国产在线2 | 成人亚洲精品777777大片 | 91在线精品一区二区 | 精品亚洲永久免费精品 | 亚洲国产成人精品女人久久久 | 欧美日韩在线视频一区二区 | 免费a大片 | 日本a在线| 精品国产乱码久久久久久久软件 | 亚洲欧美国产精品久久久久 | 亚洲a网| 国产精品久久久久久久7电影 | 久久99精品久久久久久琪琪 | 色综合88 | 国产精品久久久久久亚洲调教 | 久久9精品 | 免费成人av| 欧美成人综合在线 | 国产精品99久久久久久动医院 | 一 级 黄 色 片免费网站 | 青娱乐国产精品视频 | 不卡成人| 每日更新在线观看av | 精品成人在线视频 | 国产精品亚洲精品 | 亚洲成人av | 妞干网福利视频 | 国产在线第一页 | av在线网址观看 | 亚洲精选免费视频 | 一级片在线观看免费 | 欧美xxxx性| 欧美色图亚洲自拍 | 日韩成人一区二区 | 久久av网| 美日韩精品视频 | 欧美嘿咻 | 欧美日韩一区二区三区四区 | 激情网站免费观看 | 欧美成人一区二区三区片免费 | 中文字幕久久精品 | 亚洲av毛片一区二二区三三区 | 精品免费久久久久 | 国产精品久久久久久久久久久新郎 | 成人久久久 | 91视频免费播放 | 国产综合久久 | 亚洲狠狠爱 | 国产一区二区三区精品久久久 | 日韩精品一区二区三区视频播放 | 国产精品久久久久一区二区三区 | 国产农村妇女精品一二区 | 亚洲一区二区三区在线视频 | 美女一级 | 亚洲一区二区精品视频 | 中文字幕国产日韩 | 久视频在线观看 | 国产精品美女久久 | 日韩精品在线一区 | 久久伊人操 | 99热精品在线 | 成人国产网站 | 国产精品无码久久久久 | 日韩大尺度电影在线观看 | 欧美日韩中文字幕在线 | 成人在线网址 | 日本亚洲一区 | 亚洲www视频 | 国产精品视屏 | 欧美精品欧美极品欧美激情 | 欧洲美女7788成人免费视频 | 国产精品久久久久久久久免费高清 | 国产色在线 | 日韩视频一区二区三区四区 | 一二区视频 | 中文天堂在线观看视频 | 一区二区三区视频在线观看 | 国产中文字幕一区 | 欧美综合一区二区 | 亚洲人成中文字幕在线观看 | 成人欧美一区二区三区在线观看 | 就操成人网 | 久久www免费视频 | 在线看国产 | 福利精品在线观看 | 日韩精品一区在线视频 | 国产亚洲成av人片在线观看桃 | 狠狠操操| 日韩国产 | 国产成人精品一区二区三区视频 | 精品欧美一区二区三区久久久小说 | 亚洲欧美日韩在线一区 | 91在线精品秘密一区二区 | 亚洲一区精品在线 | 最近日韩中文字幕 | 欧美日韩视频在线 | 国产一区二区久久久 | 国产区福利 | 久久成人精品视频 | 国产成人天天爽高清视频 | 久久久精品国产 | 亚洲精品66| 亚洲国产精品久久久 | 免费在线观看一级毛片 | 欧美日韩精品亚洲 | 午夜精品久久久久久久久久久久久 | av毛片在线免费看 | 久久国产精品久久 | 男人久久天堂 | 欧美日韩一级二级三级 | 久久久久久亚洲 | 美女午夜影院 | 国产精品夜色一区二区三区 | 九九热热九九 | 亚洲成人综合在线 | 最新免费av网站 | 精品少妇一区二区 | 精品国产欧美一区二区三区成人 | 亚洲精品国产9999久久久久 | 91九色网站 | 亚洲毛片在线 | 97超碰在线免费 | www.亚洲精品| 久操国产| 亚洲美女在线视频 | 国产美女永久免费无遮挡 | 精品乱子伦一区二区三区 | 日韩在线播放一区二区三区 | 91亚洲国产成人久久精品网站 | 天天躁日日躁aaaaxxxx | 亚洲网站在线免费观看 | 99久久视频 | 欧美日韩免费一区二区三区 | 欧美日韩一| 电影k8一区二区三区久久 | 亚洲一区二区三区四区五区中文 | 啪啪的网站 | 九色国产 | av国产精品| 中文字幕三区 | a视频在线观看免费 | 青青久久| 一区二区三区精品 | 在线观看国产视频 | 免费一级在线观看 | 欧美一区在线视频 | 国产精品欧美日韩 | 午夜精品久久久久久久久久久久 | 久久久www| 国产亚洲欧美在线 | 国产免费一区二区三区最新不卡 | 亚洲免费成人 | 久久精品欧美一区二区三区麻豆 | 犬夜叉在线观看 | 夜夜超碰 | 亚洲精品一区久久久久久 | 亚洲成人福利在线观看 | 色站综合 | 亚洲一区二区三区视频 | 久久精品免费观看 | 91碰碰 | 久久久久久久久久影院 | 精品成人免费一区二区在线播放 | 久久99精品久久久久久琪琪 | 精品久久久久一区二区三区 | 日韩成人一区二区 | 蜜桃av人人夜夜澡人人爽 | 中文字幕av亚洲精品一部二部 | 亚洲精品夜夜夜 | 成人欧美一区二区三区 | 亚洲精品乱码久久久久久国产主播 | 久久久精品综合 | 6080夜射猫 | 2019亚洲日韩新视频 | 欧美久久久久久 | 国产视频精品在线观看 | 国产在线网站 | 日本精品在线 | 91精品久久久久久久久久入口 | 日韩午夜在线视频 | 97精品国产97久久久久久粉红 | 国产乱码精品一区二区三区五月婷 | 成人伊人 | 欧美日韩久久 | www.国产.com | 欧美国产免费 | 欧美在线 | 亚洲 | 日韩1区| 久草视频播放 | 人人射| 免费毛片视频 | 91精品国产综合久久久久久丝袜 | 欧美精品成人一区二区三区四区 | 亚洲男人天堂av | 亚洲成人精品久久久 | 91精品国产91综合久久蜜臀 | 成年人看的羞羞网站 | 欧美成人黑人xx视频免费观看 | 日韩精品 电影一区 亚洲 | 欧美精品一区三区 | 亚洲国产精品一区二区第一页 | 亚洲精品久久 | 天堂一区二区三区 | 久久久蜜臀 | 在线观看视频一区二区 | 国产精品视频 | 久草福利 | 精品久久久久久 | www.国产 | 福利视频二区 | 欧美在线观看免费观看视频 | 91激情在线| 亚洲精选免费视频 | 日韩一区高清视频 | 成人av一区二区三区 | 日韩五月| 激情综合网五月婷婷 | 久久成人精品 | 午夜精品久久久久久久久 | 久久久久久久国产精品 | 午夜激情福利视频 | 国产精品国产成人国产三级 | www视频在线观看 | 欧美激情视频一区二区三区在线播放 | 色综合一区 | 91亚洲一区 | 亚洲综合色视频在线观看 | 免费国产黄网站在线观看视频 | 久久久www | 日韩欧美精品一区二区三区 | 久热av在线| 久久久久久久久久影院 | 久在线视频播放免费视频 | 亚洲+变态+欧美+另类+精品 | 欧美日韩国产精品久久久久 | 久久久久久久 | 国产在线中文字幕 | 国产精品中文字幕在线观看 | 国产精品久久 | 久久久久亚洲国产 | 精品在线一区二区 | 黄色毛片在线看 | 国产亚洲一区二区三区 | 日本激情视频在线播放 | 久久久久久久久99精品 | 一区二区观看 | 天天操操 | 国产欧美精品一区二区色综合朱莉 | 成人av高清 | 91久久久久| 一本一本久久a久久精品综合妖精 | 色婷婷综合久久久中文字幕 | 国产精品视频网站 | 欧美成人高清 | 国产在线中文字幕 | 国产在线一区二区三区 | 欧美涩涩网站 | 亚洲精品三级 | 91精品入口蜜桃 | 日韩在线观看 | 亚洲在线播放 | 成人免费的视频 | 天天拍天天操 | 九九九久久久 | 精品久久久久久久久久久久久久 | 久久99er6热线精品首页蜜臀 | 日韩有码一区 | 成人理论片 | 亚洲午夜av| 99视频免费 | 国产高潮呻吟久久渣男片 | 国产日韩精品入口 | 在线欧美亚洲 | 日韩欧美一区二区三区免费观看 | 亚洲高清视频一区二区 | 成人免费视频观看视频 | 欧美成在线观看 | 国产精品久久久久aaaa九色 | 国产高潮呻吟久久渣男片 | 互换娇妻呻吟hd中文字幕 | 天天躁日日躁狠狠躁av麻豆 | 亚洲激情视频在线观看 | 播放一级黄色片 | 久久蜜桃视频 | 欧美激情在线精品一区二区三区 | 亚洲第一视频网站 | 狠久久 | 日韩成人在线播放 | 久一在线| 日韩精品一区二区三区四区五区 | 超碰天天 | 欧美精品入口蜜桃 | 天天干天天操 | 国产精品色 | 一区二区激情 | 凹凸日日摸日日碰夜夜 | 中文字幕一区二区三区四区 | 亚洲专区中文字幕 | 久操成人 | 久久久av | 国产精品18久久久久久久久 | 国产一区二区欧美 | 天天澡天天狠天天天做 | 国产精品久久久久久久 | 一区二区视频 | 在线观看中文字幕 | 美女视频久久 | 在线免费观看色视频 | 国产h在线 | 性色av一区二区三区免费看开蚌 | 国产乱码精品一区二区三区中文 | 欧美日韩不卡 | 成人福利在线 | 日韩三级中文字幕 | 亚洲一区二区三区免费在线 | avhd101在线成人播放 | 亚洲精品久久久久久久久久久久久 | 一级特黄色大片 | 国产成人在线一区 | 欧美在线a | 亚洲国产成人精品女人 | 日韩国产| 亚洲高清免费视频 | 久久九九 | 国产精品久久久久久亚洲调教 | 色综合天天综合网国产成人网 | 亚洲久久在线 | 一区二区中文字幕 | 国产在线精品一区二区 | 久久成人在线视频 | 欧美怡红院视频一区二区三区 | 亚洲福利视频在线 | 国产精品久久一区二区三区 | 国产乱视频网站 | 久久精品亚洲精品 | 奇米在线视频 | 亚洲欧美另类在线 | 日韩在线欧美 | 蜜桃一区 | 国产精品色婷婷亚洲综合看 | 国产主播久久 | 久久久久久久久久久久久九 | 日本久久网 | 天天干狠狠干 | 亚洲成人免费av | 国产麻豆乱码精品一区二区三区 | 日韩超碰在线观看 | 人人九九| 日韩午夜| av午夜电影| 国产毛片毛片 | 欧美99| 日韩精品一区二区三区中文字幕 | aaa在线| 一级毛片免费网站 | 97人人干 | 日韩a | 国产高清一区二区三区 | 久久久精品国产 | 操操操干干干 | 一区二区中文字幕 | 日韩中文在线 | 日本久久影视 | 国产欧美一区二区三区在线看 | 午夜久久久 | 国产无毛| 日韩中文在线视频 | 中文字幕综合 | 先锋av资源网 | 成人在线网 | 免费观看一区二区三区毛片 | 国产专区在线 | 欧美精品1区2区3区 欧美视频在线一区 | 日本一区二区精品视频 | 69av在线视频 | 亚洲视频精品在线 | 久久男女 | 国产成人福利 | 中文字幕在线第一页 | 91精品中文字幕一区二区三区 | 国产精品久久久久久吹潮 | 国产精品7| 国产精品成人3p一区二区三区 | 久久91精品 | 一区二区国产精品 | 犬夜叉在线观看 | 欧美成人精品 | 成人亚洲视频在线观看 | 亚洲一区二区三区在线视频 | 国产亲子乱弄免费视频 | 欧美在线一级 | 亚洲免费成人av | 亚洲日韩中文字幕一区 | a级三四级黄大片 | 国产精品99久久 | 国产精品久久久久久久久久久新郎 | 欧美国产精品一区 | 91人人| 不卡欧美 | 日韩欧美一级在线 | 一区二区日韩视频 | 欧美成人免费在线视频 | 欧美与黑人午夜性猛交久久久 | 国产精品久久久久久一级毛片 | 视频精品一区 | 91激情视频| 国产女人和拘做受视频 | 蜜桃av一区 | 日韩中文字幕在线观看 | 中文字幕亚洲字幕一区二区 | 一区二区免费在线播放 | 欧美一级毛片久久99精品蜜桃 | 国外成人在线视频网站 | 偷拍呻吟高潮91 | 999久久久国产999久久久 | 久久久精品网 | 亚洲精品国产第一综合99久久 | 亚洲精品久久久久久久久久久 | 久久精品免费一区二区三区 | 国产伦精品一区二区三区四区视频 | 91精品欧美久久久久久久 | 99久久99久久 | 国产成人精品一区二区三区视频 | 国产精品毛片久久久久久 | 天天澡天天狠天天天做 | 一区不卡| 国产精品夜夜 | youjizz国产 | h视频在线观看免费 |