久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

BlueStore事物狀態(tài)機(jī)是什么

共計(jì) 10590 個(gè)字符,預(yù)計(jì)需要花費(fèi) 27 分鐘才能閱讀完成。

本篇內(nèi)容主要講解“BlueStore 事物狀態(tài)機(jī)是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓丸趣 TV 小編來帶大家學(xué)習(xí)“BlueStore 事物狀態(tài)機(jī)是什么”吧!

前言

BlueStore 可以理解為一個(gè)支持 ACID 的本地日志型文件系統(tǒng)。所有的讀寫都是以 Transaction 進(jìn)行,又因?yàn)橹С指采w寫,所以寫流程設(shè)計(jì)的相對(duì)復(fù)雜一些,涉及到一系列的狀態(tài)轉(zhuǎn)換。我們著重分析一下狀態(tài)機(jī)、延遲指標(biāo)以及如何保證 IO 的順序性和并發(fā)性。

狀態(tài)機(jī) queue_transactions

queue_transactions 是 ObjectStore 層的統(tǒng)一入口,KVStore、MemStore、FileStore、BlueStore 都相應(yīng)的實(shí)現(xiàn)了這個(gè)接口。state_t state 變量記錄了當(dāng)前時(shí)刻事物處于哪個(gè)狀態(tài)。在創(chuàng)建 TransactionContext 的時(shí)候會(huì)將 state 初始化為 STATE_PREPARE,然后在_txc_add_transaction 中會(huì)根據(jù)操作碼類型 (opcode) 進(jìn)行不同的處理。同時(shí)會(huì)獲取 PG 對(duì)應(yīng)的 OpSequencer(每個(gè) PG 有一個(gè) OpSequencer)用來保證 PG 上的 IO 串行執(zhí)行,對(duì)于 deferred-write 會(huì)將其數(shù)據(jù)寫入 RocksDB(WAL)。

以下階段就進(jìn)入 BlueStore 狀態(tài)機(jī)了,我們以寫流程為導(dǎo)向分析狀態(tài)機(jī)的每個(gè)狀態(tài)。

STATE_PREPARE

從 state_prepare 開始已經(jīng)進(jìn)入事物的狀態(tài)機(jī)了。這個(gè)階段會(huì)調(diào)用_txc_add_transaction 將 OSD 層面的事物轉(zhuǎn)換為 BlueStore 層面的事物;然后檢查是否還有未提交的 IO,如果還有就將 state 設(shè)置為 STATE_AIO_WAIT 并調(diào)用_txc_aio_submit 提交 IO,然后退出狀態(tài)機(jī),之后 aio 完成的時(shí)候會(huì)調(diào)用回調(diào)函數(shù) txc_aio_finish 再次進(jìn)入狀態(tài)機(jī);否則就進(jìn)入 STATE_AIO_WAIT 狀態(tài)。
_txc_aio_submit 函數(shù)調(diào)用棧:

bdev- aio_submit – KernelDevice::aio_submit – io_submit 將 aio 提交到內(nèi)核 Libaio 隊(duì)列。

主要工作:準(zhǔn)備工作,生成大小寫、初始化 TransContext、deferred_txn、分配磁盤空間等。

延遲指標(biāo):l_bluestore_state_prepare_lat,從進(jìn)入狀態(tài)機(jī)到 prepare 階段完成,平均延遲大概 0.2ms 左右。

STATE_AIO_WAIT

該階段會(huì)調(diào)用_txc_finish_io 進(jìn)行 SimpleWrite 的 IO 保序等處理,然后將狀態(tài)設(shè)置為 STATE_IO_DONE 再調(diào)用_txc_state_proc 進(jìn)入下一個(gè)狀態(tài)的處理。

主要工作:對(duì) IO 保序,等待 AIO 的完成。

延遲指標(biāo):l_bluestore_state_aio_wait_lat,從 prepare 階段完成開始到 AIO 完成,平均延遲受限于設(shè)備,SSD 0.03ms 左右。

STATE_IO_DONE

完成 AIO,并進(jìn)入 STATE_KV_QUEUED 階段。會(huì)根據(jù) bluestore_sync_submit_transaction 做不同處理。該值為布爾值,默認(rèn)為 false。

如果為 true,設(shè)置狀態(tài)為 STATE_KV_SUBMITTED 并且同步提交 kv 到 RocksDB 但是沒有 sync 落盤(submit_transaction),然后 applied_kv。

如果為 false,則不用做上面的操作,但是以下操作都會(huì)做。

最后將事物放在 kv_queue 里,通過 kv_cond 通知 kv_sync_thread 去同步 IO 和元數(shù)據(jù)。

主要工作:將事物放入 kv_queue,然后通知 kv_sync_thread,osr 的 IO 保序可能會(huì) block。

延遲指標(biāo):l_bluestore_state_io_done_lat,平均延遲在 0.004ms,通常很小主要耗在對(duì) SimpleWrite 的 IO 保序處理上。

STATE_KV_QUEUED

該階段主要在 kv_sync_thread 線程中同步 IO 和元數(shù)據(jù),并且將狀態(tài)設(shè)置為 STATE_KV_SUBMITTED。具體會(huì)在異步線程章節(jié)分析 kv_sync_thread 線程。

主要工作:從 kv_sync_thread 隊(duì)列中取出事物。

延遲指標(biāo):l_bluestore_state_kv_queued_lat,從事物進(jìn)入隊(duì)列到取出事物,平均延遲在 0.08ms,因?yàn)槭菃尉€程順序處理的,所以依賴于 kv_sync_thread 處理事物的速度。

STATE_KV_SUBMITTED

等待 kv_sync_thread 中 kv 元數(shù)據(jù)和 IO 數(shù)據(jù)的 Sync 完成,然后將狀態(tài)設(shè)置為 STATE_KV_DONE 并且回調(diào) finisher 線程。

主要工作:等待 kv 元數(shù)據(jù)和 IO 數(shù)據(jù)的 Sync 完成,回調(diào) finisher 線程。

延遲指標(biāo):l_bluestore_state_kv_committing_lat,從隊(duì)列取出事物到完成 kv 同步,平均延遲 1.0ms,有極大的優(yōu)化空間。

STATE_KV_DONE

如果是 SimpleWrite,則直接將狀態(tài)設(shè)置為 STATE_FINISHING;如果是 DeferredWrite,則將狀態(tài)設(shè)置為 STATE_DEFERRED_QUEUED 并放入 deferred_queue。

主要工作:如上。

延遲指標(biāo):l_bluestore_state_kv_done_lat,平均延遲 0.0002ms,可以忽略不計(jì)。

STATE_DEFERRED_QUEUED

主要工作:將延遲 IO 放入 deferred_queue 等待提交。

延遲指標(biāo):l_bluestore_state_deferred_queued_lat,通常不小,沒有數(shù)據(jù)暫不貼出。

STATE_DEFERRED_CLEANUP

主要工作:清理延遲 IO 在 RocksDB 上的 WAL。

延遲指標(biāo):l_bluestore_state_deferred_cleanup_lat,通常不小,沒有數(shù)據(jù)暫不貼出。

STATE_FINISHING

主要工作:設(shè)置狀態(tài)為 STATE_DONE,如果還有 DeferredIO 也會(huì)提交。

延遲指標(biāo):l_bluestore_state_finishing_lat,平均延遲 0.001ms。

STATE_DONE

主要工作:標(biāo)識(shí)整個(gè) IO 完成。

延遲指標(biāo):l_bluestore_state_done_lat。

延遲分析

BlueStore 定義了狀態(tài)機(jī)的多個(gè)延遲指標(biāo),由 PerfCounters 采集,函數(shù)為 BlueStore::_init_logger()。

可以使用 ceph daemon osd.0 perf dump 或者 ceph daemonperf osd.0 來查看對(duì)應(yīng)的延遲情況。

除了每個(gè)狀態(tài)的延遲,我們通常也會(huì)關(guān)注以下兩個(gè)延遲指標(biāo):

b.add_time_avg(l_bluestore_kv_lat,  kv_lat ,
  Average kv_thread sync latency ,  k_l ,
 
b.add_time_avg(l_bluestore_commit_lat,  commit_lat ,
  Average commit latency ,  c_l ,

BlueStore 延遲主要花費(fèi)在 l_bluestore_state_kv_committing_lat 也即 c_l,大概 1ms 左右。

BlueStore 統(tǒng)計(jì)狀態(tài)機(jī)每個(gè)階段延遲的方法如下:

//  該階段延遲  =  上階段完成到該階段結(jié)束
void log_state_latency(PerfCounters *logger, int state) { utime_t lat, now = ceph_clock_now();
 lat = now - last_stamp;
 logger- tinc(state, lat);
 last_stamp = now;
}

在塊存儲(chǔ)的使用場(chǎng)景中,除了用戶并發(fā) IO 外,通常用戶也會(huì)使用 dd 等串行 IO 的命令,此時(shí)便受限于讀寫的絕對(duì)延遲,擴(kuò)容加機(jī)器、增加線程數(shù)等橫向擴(kuò)展的優(yōu)化便是無效的,所以我們需要關(guān)注兩方面的延遲:并發(fā) IO 延遲、串行 IO 延遲。

并發(fā) IO 延遲優(yōu)化:kv_sync_thread、kv_finalize_thread 多線程化;自定義 WAL;async read。

串行 IO 延遲優(yōu)化:并行提交元數(shù)據(jù)、數(shù)據(jù);將 sync 操作與其他狀態(tài)并行處理。

IO 保序

保證 IO 的順序性以及并發(fā)性是分布式存儲(chǔ)必然面臨的一個(gè)問題。因?yàn)?BlueStore 使用異步 IO,后提交的 IO 可能比早提交的 IO 完成的早,所以更要保證 IO 的順序,防止數(shù)據(jù)發(fā)生錯(cuò)亂。客戶端可能會(huì)對(duì) PG 中的一個(gè) Object 連續(xù)提交多次讀寫請(qǐng)求,每次請(qǐng)求對(duì)應(yīng)一個(gè) Transaction,在 OSD 層面通過 PGLock 將并發(fā)的讀寫請(qǐng)求在 PG 層面串行化,然后按序依次提交到 ObjectStore 層,ObjectStore 層通過 PG 的 OpSequencer 保證順序處理讀寫請(qǐng)求。

BlueStore 寫類型有 SimpleWrite、DeferredWrite 兩種,所以我們分析一下 SimpleWrite、DeferredWrite 下的 IO 保序問題。

SimpleWrite

因?yàn)?STATE_AIO_WAIT 階段使用 Libaio,所以需要保證 PG 對(duì)應(yīng)的 OpSequencer 中的 txc 按排隊(duì)的先后順序依次進(jìn)入 kv_queue 被 kv_sync_thread 處理,也即 txc 在 OpSequencer 中的順序和在 kv_queue 中的順序是一致的。

void BlueStore::_txc_finish_io(TransContext *txc)
 //  獲取 txc 所屬的 OpSequencer,并且加鎖,保證互斥訪問 osr
 OpSequencer *osr = txc- osr.get();
 std::lock_guard std::mutex  l(osr- qlock);
 
 //  設(shè)置狀態(tài)機(jī)的 state 為 STATE_IO_DONE
 txc- state = TransContext::STATE_IO_DONE;
 
 //  清除 txc 正在運(yùn)行的 aio
 txc- ioc.running_aios.clear();
 
 //  定位當(dāng)前 txc 在 osr 的位置
 OpSequencer::q_list_t::iterator p = osr- q.iterator_to(*txc);
 
 while (p != osr- q.begin()) {
 --p;
 //  如果前面還有未完成 IO 的 txc,那么需要停止當(dāng)前 txc 操作,等待前面 txc 完成 IO。 //  目的是:確保之前 txc 的 IO 都完成。 if (p- state   TransContext::STATE_IO_DONE) {
 return;
 }
 
 //  前面的 txc 已經(jīng)進(jìn)入大于等于 STATE_KV_QUEUED 的狀態(tài)了,那么遞增 p 并退出循環(huán)。 //  目的是:找到狀態(tài)為 STATE_IO_DONE 的且在 osr 中排序最靠前的 txc。 if (p- state   TransContext::STATE_IO_DONE) {
 ++p;
 break;
 }
 }
 
 //  依次處理狀態(tài)為 STATE_IO_DONE 的 tx
 //  將 txc 放入 kv_sync_thread 的 kv_queue、kv_queue_unsubmitted 隊(duì)列
 do { _txc_state_proc( *p++);
 } while (p != osr- q.end()   p- state == TransContext::STATE_IO_DONE);
 ......
}

DeferredWrite

DeferredWrite 在 IO 的時(shí)候也是通過 Libaio 提交到內(nèi)核 Libaio 隊(duì)列進(jìn)行寫數(shù)據(jù),也需要保證 IO 的順序性。

相應(yīng)的數(shù)據(jù)結(jié)構(gòu)如下:

class BlueStore {
 typedef boost::intrusive::list 
 OpSequencer, boost::intrusive::member_hook 
 OpSequencer, boost::intrusive::list_member_hook ,
  OpSequencer::deferred_osr_queue_item 
 deferred_osr_queue_t;
 
 // osr s with deferred io pending
 deferred_osr_queue_t deferred_queue;
 
class OpSequencer {
 DeferredBatch *deferred_running = nullptr;
 DeferredBatch *deferred_pending = nullptr;
 
struct DeferredBatch {
 OpSequencer *osr;
 
 // txcs in this batch
 deferred_queue_t txcs;
}

BlueStore 內(nèi)部包含一個(gè)成員變量 deferred_queue;deferred_queue 隊(duì)列包含需要執(zhí)行 DeferredIO 的 OpSequencer;每個(gè) OpSequencer 包含 deferred_running 和 deferred_pending 兩個(gè) DeferredBatch 類型的變量;DeferredBatch 包含一個(gè) txc 數(shù)組。

如果 PG 有寫請(qǐng)求,會(huì)在 PG 對(duì)應(yīng)的 OpSequencer 中的 deferred_pending 中排隊(duì)加入 txc,待時(shí)機(jī)成熟的時(shí)候,一次性提交所有 txc 給 Libaio,執(zhí)行完成后才會(huì)進(jìn)行下一次提交,這樣不會(huì)導(dǎo)致 DeferredIO 亂序。

void BlueStore::_deferred_queue(TransContext *txc)
 deferred_lock.lock();
 //  排隊(duì) osr
 if (!txc- osr- deferred_pending   !txc- osr- deferred_running) { deferred_queue.push_back(*txc- osr);
 }
 
 //  追加 txc 到 deferred_pending 中
 txc- osr- deferred_pending- txcs.push_back(*txc);
 
 _deferred_submit_unlock(txc- osr.get());
 ......
 
void BlueStore::_deferred_submit_unlock(OpSequencer *osr)
 ......
 //  切換指針,保證每次操作完成后才會(huì)進(jìn)行下一次提交
 osr- deferred_running = osr- deferred_pending;
 osr- deferred_pending = nullptr;
 ......
 
 while (true) {
 ......
 //  準(zhǔn)備所有 txc 的寫 buffer
 int r = bdev- aio_write(start, bl,  b- ioc, false);
 }
 
 ......
 //  一次性提交所有 txc
 bdev- aio_submit(b- ioc);
}

線程隊(duì)列

線程 + 隊(duì)列是實(shí)現(xiàn)異步操作的基礎(chǔ)。BlueStore 的一次 IO 經(jīng)過狀態(tài)機(jī)要進(jìn)入多個(gè)隊(duì)列并被不同的線程處理然后回調(diào),線程 + 隊(duì)列是 BlueStore 事物狀態(tài)機(jī)的重要組成部分。BlueStore 中的線程大致有 7 種。

mempool_thread:無隊(duì)列,后臺(tái)監(jiān)控內(nèi)存的使用情況,超過內(nèi)存使用的限制便會(huì)做 trim。

aio_thread:隊(duì)列為 Libaio 內(nèi)核 queue,收割完成的 aio 事件。

discard_thread:隊(duì)列為 discard_queued,對(duì) SSD 磁盤上的 extent 做 Trim。

kv_sync_thread:隊(duì)列為 kv_queue、deferred_done_queue、deferred_stable_queue,sync 元數(shù)據(jù)和數(shù)據(jù)。

kv_finalize_thread:隊(duì)列為 kv_committing_to_finalize、deferred_stable_to_finalize,執(zhí)行清理功能。

deferred_finisher:調(diào)用回調(diào)函數(shù)提交 DeferredIO 的請(qǐng)求。

finishers:多個(gè)回調(diào)線程 Finisher,通知用戶請(qǐng)求完成。

我們主要分析 aio_thread、kv_sync_thread、kv_finalize_thread。

aio_thread

aio_thread 比較簡(jiǎn)單,屬于 KernelDevice 模塊的,主要作用是收割完成的 aio 事件,并觸發(fā)回調(diào)函數(shù)。

void KernelDevice::_aio_thread() { while (!aio_stop) {
 ......
 //  獲取完成的 aio
 int r = aio_queue.get_next_completed(cct- _conf- bdev_aio_poll_ms, aio, max);
 //  設(shè)置 flush 標(biāo)志為 true。 io_since_flush.store(true);
 //  獲取 aio 的返回值
 long r = aio[i]- get_return_value();
 ......
 //  調(diào)用 aio 完成的回調(diào)函數(shù)
 if (ioc- priv) { if (--ioc- num_running == 0) { aio_callback(aio_callback_priv, ioc- priv);
 }
 } 
 }
}

涉及延遲指標(biāo):state_aio_wait_lat、state_io_done_lat。

kv_sync_thread

當(dāng) IO 完成后,要么將 txc 放入隊(duì)列,要么將 dbh 放入隊(duì)列,雖然對(duì)應(yīng)不同隊(duì)列,但都是由 kv_sync_thread 執(zhí)行后續(xù)操作。

對(duì)于 SimpleWrite,都是寫新的磁盤 block(如果是 cow,也是寫新的 block,只是事務(wù)中 k / v 操作增加對(duì)舊的 block 的回收操作),所以先由 aio_thread 寫 block,再由 kv_sync_thread 同步元信息,無論什么時(shí)候掛掉,數(shù)據(jù)都不會(huì)損壞。

對(duì)于 DeferredWrite,在事物的 prepare 階段將需要 DeferredWrite 的數(shù)據(jù)作為 k / v 對(duì) (也稱為 WAL) 寫入基于 RocksDB 封裝的 db_transaction 中,此時(shí)還在內(nèi)存,kv_sync_thread 第一次的 commit 操作中,將 wal 持久化在了 k / v 系統(tǒng)中,然后進(jìn)行后續(xù)的操作,異常的情況,可以通過回放 wal,數(shù)據(jù)也不會(huì)損壞。

kv_sync_thread 主要執(zhí)行的操作為:在 Libaio 寫完數(shù)據(jù)后,需要通過 kv_sync_thread 更新元數(shù)據(jù) k /v,主要包含 object 的 Onode、擴(kuò)展屬性、FreelistManager 的磁盤空間信息等等,這些必須按順序操作。

涉及的隊(duì)列如下:

kv_queue:需要執(zhí)行 commit 的 txc 隊(duì)列。將 kv_queue 中的 txc 存入 kv_committing 中,并提交給 RocksDB,即執(zhí)行操作 db- submit_transaction,設(shè)置狀態(tài)為 STATE_KV_SUBMITTED,并將 kv_committing 中的 txc 放入 kv_committing_to_finalize,等待線程 kv_finalize_thread 執(zhí)行。

deferred_done_queue:已經(jīng)完成 DeferredIO 操作的 dbh 隊(duì)列,還沒有 sync 磁盤。這個(gè)隊(duì)列的 dbh 會(huì)有兩種結(jié)果: 1) 如果沒有做 flush 操作,會(huì)將其放入 deferred_stable_queue 待下次循環(huán)繼續(xù)處理 2) 如果做了 flush 操作,說明數(shù)據(jù)已經(jīng)落盤,即已經(jīng)是 stable 的了,直接將其插入 deferred_stable_queue 隊(duì)列。這里 stable 的意思就是數(shù)據(jù)已經(jīng) sync 到磁盤了,前面 RocksDB 中記錄的 wal 沒用可以刪除了。

deferred_stable_queue:DeferredIO 已經(jīng)落盤,等待清理 RocksDB 中的 WAL。依次操作 dbh 中的 txc,將 RocksDB 中的 wal 刪除,然后 dbh 入隊(duì)列 deferred_stable_to_finalize,等待線程 kv_finalize_thread 執(zhí)行。

void BlueStore::_kv_sync_thread() { while (true) {
 //  交換指針
 kv_committing.swap(kv_queue);
 kv_submitting.swap(kv_queue_unsubmitted);
 deferred_done.swap(deferred_done_queue);
 deferred_stable.swap(deferred_stable_queue)
 
 //  處理  deferred_done_queue
 if (force_flush) {
 // flush/barrier on block device
 bdev- flush();
 // if we flush then deferred done are now deferred stable
 deferred_stable.insert(deferred_stable.end(),
 deferred_done.begin(),
 deferred_done.end());
 deferred_done.clear();
 }
 
 //  處理  kv_queue
 for (auto txc : kv_committing) {
 int r = cct- _conf- bluestore_debug_omit_kv_commit
 ? 0
 : db- submit_transaction(txc- 
 _txc_applied_kv(txc);
 }
 
 //  處理  deferred_stable_queue
 for (auto b : deferred_stable) { for (auto  txc : b- txcs) { get_deferred_key(wt.seq,  key);
 synct- rm_single_key(PREFIX_DEFERRED, key);
 }
 }
 
 // submit synct synchronously (block and wait for it to commit)
 //  同步 kv,有設(shè)置 bluefs_extents、刪除 wal 兩種操作
 int r = cct- _conf- bluestore_debug_omit_kv_commit
 ? 0
 : db- submit_transaction_sync(synct);
 
 //  放入 finalize 線程隊(duì)列,并通知其處理。 std::unique_lock std::mutex  m(kv_finalize_lock);
 kv_committing_to_finalize.swap(kv_committing);
 deferred_stable_to_finalize.swap(deferred_stable);
 kv_finalize_cond.notify_one();
 }
}

涉及延遲指標(biāo):state_kv_queued_lat、state_kv_committing_lat、kv_lat

kv_finalize_thread

清理線程,包含兩個(gè)隊(duì)列:

kv_committing_to_finalize:再次調(diào)用_txc_state_proc 進(jìn)入狀態(tài)機(jī),設(shè)置狀態(tài)為 STATE_KV_DONE,并執(zhí)行回調(diào)函數(shù)通知用戶 io 操作完成。

deferred_stable_to_finalize:遍歷 deferred_stable 中的 dbh,調(diào)用_txc_state_proc 進(jìn)入狀態(tài)機(jī),設(shè)置狀態(tài)為 STATE_FINISHING,繼續(xù)調(diào)用_txc_finish,設(shè)置狀態(tài)為 STATE_DONE,狀態(tài)機(jī)結(jié)束,事物完成。

void BlueStore::_kv_finalize_thread() { while (true) {
 //  交換指針
 kv_committed.swap(kv_committing_to_finalize);
 deferred_stable.swap(deferred_stable_to_finalize);
 
 //  處理 kv_committing_to_finalize 隊(duì)列
 while (!kv_committed.empty()) { TransContext *txc = kv_committed.front();
 _txc_state_proc(txc);
 kv_committed.pop_front();
 }
 
 //  處理 deferred_stable_to_finalize
 for (auto b : deferred_stable) { auto p = b- txcs.begin();
 while (p != b- txcs.end()) {
 TransContext *txc =  
 p = b- txcs.erase(p); // unlink here because
 _txc_state_proc(txc); // this may destroy txc
 }
 delete b;
 }
 deferred_stable.clear();
 }
}

涉及延遲指標(biāo):state_deferred_cleanup_lat、state_finishing_lat

IO 狀態(tài)

主要分為 SimpleWrite、DeferredWrite、SimpleWrite+DeferredWrite。

到此,相信大家對(duì)“BlueStore 事物狀態(tài)機(jī)是什么”有了更深的了解,不妨來實(shí)際操作一番吧!這里是丸趣 TV 網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

正文完
 
丸趣
版權(quán)聲明:本站原創(chuàng)文章,由 丸趣 2023-08-16發(fā)表,共計(jì)10590字。
轉(zhuǎn)載說明:除特殊說明外本站除技術(shù)相關(guān)以外文章皆由網(wǎng)絡(luò)搜集發(fā)布,轉(zhuǎn)載請(qǐng)注明出處。
評(píng)論(沒有評(píng)論)
主站蜘蛛池模板: 军事| 会同县| 科技| 禄劝| 新竹县| 合山市| 云和县| 扶绥县| 特克斯县| 呼和浩特市| 商水县| 全州县| 龙山县| 瓦房店市| 台前县| 阜宁县| 隆化县| 九龙县| 开封市| 曲阳县| 黔西县| 石阡县| 襄汾县| 桐柏县| 山阳县| 永新县| 理塘县| 陇南市| 永年县| 宁阳县| 安岳县| 新建县| 团风县| 称多县| 南投县| 宁南县| 横峰县| 抚顺市| 奎屯市| 龙海市| 建平县|