中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

商業(yè)網(wǎng)站開(kāi)發(fā)入門(mén)選課百度的廣告

商業(yè)網(wǎng)站開(kāi)發(fā)入門(mén)選課,百度的廣告,網(wǎng)站頁(yè)面設(shè)計(jì)需求,珠海網(wǎng)站建設(shè)電話文章目錄 Redis分布式鎖方案:SETNX EXPIRE基本原理比較好的實(shí)現(xiàn)會(huì)產(chǎn)生四個(gè)問(wèn)題 幾種解決原子性的方案方案:SETNX value值是(系統(tǒng)時(shí)間過(guò)期時(shí)間)方案:使用Lua腳本(包含SETNX EXPIRE兩條指令)方案:SET的擴(kuò)展…

文章目錄

  • Redis分布式鎖
    • 方案:SETNX + EXPIRE
      • 基本原理
      • 比較好的實(shí)現(xiàn)
      • 會(huì)產(chǎn)生四個(gè)問(wèn)題
    • 幾種解決原子性的方案
      • 方案:SETNX + value值是(系統(tǒng)時(shí)間+過(guò)期時(shí)間)
      • 方案:使用Lua腳本(包含SETNX + EXPIRE兩條指令)
      • 方案:SET的擴(kuò)展命令(SET EX PX NX)
      • 會(huì)出現(xiàn)的問(wèn)題
    • 方案: 開(kāi)源框架:Redisson
    • 方案:多機(jī)實(shí)現(xiàn)的分布式鎖Redlock
    • 總結(jié)
    • 參考鏈接:

Redis分布式鎖

方案:SETNX + EXPIRE

基本原理

SETNX 是SET IF NOT EXISTS的簡(jiǎn)寫(xiě).日常命令格式是SETNX key value,如果 key不存在,則SETNX成功返回1,如果這個(gè)key已經(jīng)存在了,則返回0。
redis語(yǔ)法:
使用 SETNX 命令設(shè)置鍵,值為鎖的標(biāo)識(shí)
鍵名為 lock_key,值為鎖標(biāo)識(shí) lock_value
SETNX 返回 1 表示成功設(shè)置,0 表示鍵已存在
SETNX lock_key lock_value
使用 EXPIRE 命令設(shè)置鍵的過(guò)期時(shí)間(例如,設(shè)置為 10 秒)
EXPIRE lock_key 10

用java來(lái)實(shí)現(xiàn):

 ValueOperations<String, String> valueOps = redisTemplate.opsForValue();// 使用 setIfAbsent 方法設(shè)置鍵值對(duì),僅當(dāng)鍵不存在時(shí)才進(jìn)行設(shè)置boolean isSet = valueOps.setIfAbsent(key, value);if (isSet) {// 如果成功設(shè)置,再使用 expire 方法設(shè)置過(guò)期時(shí)間redisTemplate.expire(key, ttlInSeconds, java.util.concurrent.TimeUnit.SECONDS);System.out.println("Key set successfully with TTL!");} else {System.out.println("Key already exists, not set.");}

比較好的實(shí)現(xiàn)

  private static final String LOCK_SUCCESS = "OK";private static final String SET_IF_NOT_EXIST = "NX";private static final String SET_WITH_EXPIRE_TIME = "PX";/*** 嘗試獲取分布式鎖* @param jedis Redis客戶端* @param lockKey 鎖* @param requestId 請(qǐng)求標(biāo)識(shí)* @param expireTime 超期時(shí)間* @return 是否獲取成功*/public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) {String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);if (LOCK_SUCCESS.equals(result)) {return true;}return false;}

第一個(gè)為key,我們使用key來(lái)當(dāng)鎖,因?yàn)閗ey是唯一的。
第二個(gè)為value,我們傳的是requestId,很多童鞋可能不明白,有key作為鎖不就夠了嗎,為什么還要用到value?原因就是我們?cè)谏厦嬷v到可靠性時(shí),分布式鎖要滿足第四個(gè)條件解鈴還須系鈴人,通過(guò)給value賦值為requestId,我們就知道這把鎖是哪個(gè)請(qǐng)求加的了,在解鎖的時(shí)候就可以有依據(jù)。requestId可以使用UUID.randomUUID().toString()方法生成。
第三個(gè)為nxxx,這個(gè)參數(shù)我們填的是NX,意思是SET IF NOT EXIST,即當(dāng)key不存在時(shí),我們進(jìn)行set操作;若key已經(jīng)存在,則不做任何操作;
第四個(gè)為expx,這個(gè)參數(shù)我們傳的是PX,意思是我們要給這個(gè)key加一個(gè)過(guò)期的設(shè)置,具體時(shí)間由第五個(gè)參數(shù)決定。
第五個(gè)為time,與第四個(gè)參數(shù)相呼應(yīng),代表key的過(guò)期時(shí)間。

會(huì)產(chǎn)生四個(gè)問(wèn)題

1、setnx和expire兩個(gè)命令分開(kāi)了,不是原子操作。如果執(zhí)行完setnx加鎖,正要執(zhí)行expire設(shè)置過(guò)期時(shí)間時(shí),進(jìn)程crash或者要重啟維護(hù)了,那么這個(gè)鎖就“長(zhǎng)生不老”了,別的線程永遠(yuǎn)獲取不到鎖啦。
2、超時(shí)解鎖會(huì)導(dǎo)致并發(fā)問(wèn)題,如果兩個(gè)線程同時(shí)要獲取鎖,此時(shí)所恰好過(guò)期,此時(shí)這兩個(gè)線程能夠同時(shí)進(jìn)入,產(chǎn)生并發(fā)問(wèn)題
3、不可重入,同一個(gè)線程想要同時(shí)獲得這個(gè)鎖兩次實(shí)際是是不支持的
4、無(wú)法等待鎖釋放,在沒(méi)有獲取鎖的時(shí)候會(huì)直接返回,沒(méi)有等待時(shí)間。

其中原子性問(wèn)題是一個(gè)最重要的問(wèn)題,因此有了下面的解決方案。

幾種解決原子性的方案

方案:SETNX + value值是(系統(tǒng)時(shí)間+過(guò)期時(shí)間)

實(shí)際上是一種邏輯過(guò)期時(shí)間,將過(guò)期的時(shí)間作為value用setnx的value值里,如果加鎖失敗則拿出value校驗(yàn)一下即可。
java實(shí)現(xiàn)

long expires = System.currentTimeMillis() + expireTime; //系統(tǒng)時(shí)間+設(shè)置的過(guò)期時(shí)間
String expiresStr = String.valueOf(expires);// 如果當(dāng)前鎖不存在,返回加鎖成功
if (jedis.setnx(key_resource_id, expiresStr) == 1) {return true;
}
// 如果鎖已經(jīng)存在,獲取鎖的過(guò)期時(shí)間
String currentValueStr = jedis.get(key_resource_id);// 如果獲取到的過(guò)期時(shí)間,小于系統(tǒng)當(dāng)前時(shí)間,表示已經(jīng)過(guò)期
if (currentValueStr != null && Long.parseLong(currentValueStr) < System.currentTimeMillis()) {// 鎖已過(guò)期,獲取上一個(gè)鎖的過(guò)期時(shí)間,并設(shè)置現(xiàn)在鎖的過(guò)期時(shí)間(不了解redis的getSet命令的小伙伴,可以去官網(wǎng)看下哈)String oldValueStr = jedis.getSet(key_resource_id, expiresStr);if (oldValueStr != null && oldValueStr.equals(currentValueStr)) {// 考慮多線程并發(fā)的情況,只有一個(gè)線程的設(shè)置值和當(dāng)前值相同,它才可以加鎖return true;}
}
//其他情況,均返回加鎖失敗
return false;
}

方案:使用Lua腳本(包含SETNX + EXPIRE兩條指令)

實(shí)現(xiàn)原理,調(diào)用lua代碼,一個(gè)lua腳本是原子的。

if redis.call('setnx',KEYS[1],ARGV[1]) == 1 thenredis.call('expire',KEYS[1],ARGV[2])
elsereturn 0
end;

java代碼:

 String lua_scripts = "if redis.call('setnx',KEYS[1],ARGV[1]) == 1 then" +" redis.call('expire',KEYS[1],ARGV[2]) return 1 else return 0 end";   
Object result = jedis.eval(lua_scripts, Collections.singletonList(key_resource_id), Collections.singletonList(values));
//判斷是否成功
return result.equals(1L);

方案:SET的擴(kuò)展命令(SET EX PX NX)

保證SETNX + EXPIRE兩條指令的原子性,我們還可以巧用Redis的SET指令擴(kuò)展參數(shù)
例如:SET key value[EX seconds][PX milliseconds][NX|XX],它也是原子性的!
語(yǔ)法如下:

SET key value[EX seconds][PX milliseconds][NX|XX]NX :表示key不存在的時(shí)候,才能set成功,也即保證只有第一個(gè)客戶端請(qǐng)求才能獲得鎖,而其他客戶端請(qǐng)求只能等其釋放鎖,才能獲取。
EX seconds :設(shè)定key的過(guò)期時(shí)間,時(shí)間單位是秒。
PX milliseconds: 設(shè)定key的過(guò)期時(shí)間,單位為毫秒
XX: 僅當(dāng)key存在時(shí)設(shè)置值

java代碼:

if(jedis.set(key_resource_id, lock_value, "NX", "EX", 100s) == 1){ //加鎖try {do something  //業(yè)務(wù)處理}catch(){}finally {jedis.del(key_resource_id); //釋放鎖}
}

會(huì)出現(xiàn)的問(wèn)題

這種方案能解決方案一的原子性問(wèn)題,但是依然會(huì)存在很大的問(wèn)題,如下所示:
1、時(shí)鐘不同步:如果不同的節(jié)點(diǎn)的系統(tǒng)時(shí)鐘不同步,可能導(dǎo)致鎖的過(guò)期時(shí)間計(jì)算不準(zhǔn)確。
解決方案:使用相對(duì)時(shí)間而非絕對(duì)時(shí)間,或者使用時(shí)鐘同步工具確保系統(tǒng)時(shí)鐘同步。
2、死鎖:在某些情況下,可能出現(xiàn)死鎖,例如由于網(wǎng)絡(luò)問(wèn)題導(dǎo)致鎖的釋放操作未能執(zhí)行。
解決方案:使用帶有超時(shí)和重試的鎖獲取和釋放機(jī)制,確保在一定時(shí)間內(nèi)能夠正常操作。
3、鎖過(guò)期與業(yè)務(wù)未完成:如果業(yè)務(wù)邏輯執(zhí)行時(shí)間超過(guò)了設(shè)置的過(guò)期時(shí)間,鎖可能在業(yè)務(wù)未完成時(shí)自動(dòng)過(guò)期,導(dǎo)致其他客戶端獲取到鎖。
解決方案:可以設(shè)置更長(zhǎng)的過(guò)期時(shí)間,確保業(yè)務(wù)有足夠的時(shí)間完成?;蛘咴跇I(yè)務(wù)未完成時(shí),通過(guò)更新鎖的過(guò)期時(shí)間來(lái)延長(zhǎng)鎖的生命周期。
4、鎖的爭(zhēng)用:多個(gè)客戶端同時(shí)嘗試獲取鎖,可能導(dǎo)致鎖的頻繁爭(zhēng)用。
解決方案:可以使用帶有重試機(jī)制的獲取鎖操作,或者采用更復(fù)雜的鎖實(shí)現(xiàn),如 Redlock 算法。
5、鎖的釋放問(wèn)題:客戶端獲取鎖后發(fā)生異?;蛭茨苷a尫沛i,可能導(dǎo)致其他客戶端無(wú)法獲取鎖。
解決方案:使用 SET 命令設(shè)置鎖的值,并在釋放鎖時(shí)檢查當(dāng)前值是否匹配。只有匹配時(shí)才執(zhí)行釋放鎖的操作。
6、鎖被別的線程誤刪:假設(shè)線程a執(zhí)行完后,去釋放鎖。但是它不知道當(dāng)前的鎖可能是線程b持有的(線程a去釋放鎖時(shí),有可能過(guò)期時(shí)間已經(jīng)到了,此時(shí)線程b進(jìn)來(lái)占有了鎖)。那線程a就把線程b的鎖釋放掉了,但是線程b臨界區(qū)業(yè)務(wù)代碼可能都還沒(méi)執(zhí)行完。
解決方案:SET EX PX NX + 校驗(yàn)唯一隨機(jī)值,給value值設(shè)置一個(gè)標(biāo)記當(dāng)前線程唯一的隨機(jī)數(shù),在刪除的時(shí)候,校驗(yàn)一下,需要用亂

方案: 開(kāi)源框架:Redisson

總結(jié)一下上面的解決問(wèn)題的歷程和問(wèn)題,用SETNX+EXPIRE可以解決分布式鎖的問(wèn)題,但是這種方式不是原子性操作。因此,在提出的三種原子性操作解決方法,但是依然會(huì)出現(xiàn)幾個(gè)問(wèn)題,在會(huì)出現(xiàn)的問(wèn)題中簡(jiǎn)單羅列了幾種問(wèn)題與解決方法,其中問(wèn)題3中有鎖過(guò)期與業(yè)務(wù)未完成有一個(gè)系統(tǒng)的解決方案,即接下來(lái)介紹的Redison。
Redisson 是一個(gè)基于 Redis 的 Java 驅(qū)動(dòng)庫(kù),提供了分布式、高性能的 Java 對(duì)象操作服務(wù),這里只探討分布式鎖的原理:
在這里插入圖片描述

只要線程一加鎖成功,就會(huì)啟動(dòng)一個(gè)watch dog看門(mén)狗,它是一個(gè)后臺(tái)線程,會(huì)每隔10秒檢查一下,如果線程1還持有鎖,那么就會(huì)不斷的延長(zhǎng)鎖key的生存時(shí)間。因此,Redisson就是使用Redisson解決了鎖過(guò)期釋放,業(yè)務(wù)沒(méi)執(zhí)行完問(wèn)題。

Watchdog 定期續(xù)期鎖:
當(dāng)客戶端成功獲取鎖后,Redisson 啟動(dòng)一個(gè) Watchdog 線程,該線程會(huì)定期(通常是鎖過(guò)期時(shí)間的一半)檢查鎖是否過(guò)期,并在過(guò)期前對(duì)鎖進(jìn)行續(xù)期。
Watchdog 使用 Lua 腳本確保原子性:
為了確保 Watchdog 操作的原子性,Redisson 使用 Lua 腳本執(zhí)行 Watchdog 操作。這樣在 Watchdog 檢查和續(xù)期鎖的過(guò)程中,可以保證整個(gè)操作是原子的,防止出現(xiàn)競(jìng)爭(zhēng)條件。
Watchdog 續(xù)期鎖的過(guò)期時(shí)間:
Watchdog 線程會(huì)通過(guò)使用 PEXPIRE 或者 EXPIRE 命令來(lái)續(xù)期鎖的過(guò)期時(shí)間。這樣在業(yè)務(wù)未完成時(shí),鎖的過(guò)期時(shí)間會(huì)不斷延長(zhǎng),直到業(yè)務(wù)完成釋放鎖。

方案:多機(jī)實(shí)現(xiàn)的分布式鎖Redlock

Redisson分布式鎖會(huì)有個(gè)缺陷,就是在Redis哨兵模式下:客戶端1 對(duì)某個(gè) master節(jié)點(diǎn) 寫(xiě)入了redisson鎖,此時(shí)會(huì)異步復(fù)制給對(duì)應(yīng)的 slave節(jié)點(diǎn)。但是這個(gè)過(guò)程中一旦發(fā)生master節(jié)點(diǎn)宕機(jī),主備切換,slave節(jié)點(diǎn)從變?yōu)榱?master節(jié)點(diǎn)。
這時(shí) 客戶端2 來(lái)嘗試加鎖的時(shí)候,在新的master節(jié)點(diǎn)上也能加鎖,此時(shí)就會(huì)導(dǎo)致多個(gè)客戶端對(duì)同一個(gè)分布式鎖完成了加鎖。
這時(shí)系統(tǒng)在業(yè)務(wù)語(yǔ)義上一定會(huì)出現(xiàn)問(wèn)題, 導(dǎo)致各種臟數(shù)據(jù)的產(chǎn)生 。
因此有了Redlock
Redlock:全名叫做 Redis Distributed Lock;即使用redis實(shí)現(xiàn)的分布式鎖
使用場(chǎng)景:多個(gè)服務(wù)間保證同一時(shí)刻同一時(shí)間段內(nèi)同一用戶只能有一個(gè)請(qǐng)求(防止關(guān)鍵業(yè)務(wù)出現(xiàn)并發(fā)攻擊);
基本原理:
按順序向5個(gè)master節(jié)點(diǎn)請(qǐng)求加鎖(注意這五個(gè)節(jié)點(diǎn)不是哨兵和master-slaver)
根據(jù)設(shè)置的超時(shí)時(shí)間來(lái)判斷,是不是要跳過(guò)該master節(jié)點(diǎn)。
如果大于等于三個(gè)節(jié)點(diǎn)加鎖成功,并且使用的時(shí)間小于鎖的有效期,即可認(rèn)定加鎖成功啦。
如果獲取鎖失敗,解鎖!
1、時(shí)鐘漂移問(wèn)題:
問(wèn)題描述: 不同的服務(wù)器上的系統(tǒng)時(shí)鐘可能存在一定的漂移,導(dǎo)致在不同節(jié)點(diǎn)上計(jì)算鎖的過(guò)期時(shí)間不一致。
解決方案: 使用 NTP 等工具同步服務(wù)器時(shí)鐘,確保各個(gè)節(jié)點(diǎn)時(shí)鐘同步。此外,可以選擇使用更精確的鎖實(shí)現(xiàn),如 Redisson 的 Redlock 的改進(jìn)版本,可以在獲取鎖時(shí)計(jì)算一個(gè)時(shí)鐘偏移量,使得各個(gè)節(jié)點(diǎn)的時(shí)鐘更一致。
2. 網(wǎng)絡(luò)分區(qū)和節(jié)點(diǎn)故障:
問(wèn)題描述: 網(wǎng)絡(luò)分區(qū)或節(jié)點(diǎn)故障可能導(dǎo)致鎖的不一致?tīng)顟B(tài)。
解決方案: 針對(duì)網(wǎng)絡(luò)分區(qū),可以采用心跳機(jī)制定期檢測(cè)節(jié)點(diǎn)的健康狀態(tài)。對(duì)于節(jié)點(diǎn)故障,可以使用更多的節(jié)點(diǎn)(超過(guò)一半)以確保容錯(cuò)性。另外,可以考慮使用 Redis Sentinel 或 Redis Cluster 等 Redis 提供的高可用性方案,以降低節(jié)點(diǎn)故障的影響。
3. 性能代價(jià)問(wèn)題:
問(wèn)題描述: Redlock 的性能代價(jià)相對(duì)較高,因?yàn)樾枰诙鄠€(gè)節(jié)點(diǎn)上執(zhí)行鎖的獲取和釋放操作。
解決方案: 對(duì)于一些對(duì)性能要求較高的場(chǎng)景,可以考慮使用更輕量級(jí)的鎖算法,例如基于單一節(jié)點(diǎn)的分布式鎖實(shí)現(xiàn)。在一些場(chǎng)景下,性能可能更為重要。
4. 容錯(cuò)性和安全性:
問(wèn)題描述: 由于 Redis 是基于內(nèi)存的數(shù)據(jù)庫(kù),節(jié)點(diǎn)故障可能導(dǎo)致數(shù)據(jù)丟失。另外,需要確保所有的 Redis 節(jié)點(diǎn)都是可信任的。
解決方案: 在容錯(cuò)性方面,可以通過(guò)配置 Redis Sentinel 或 Redis Cluster 來(lái)提高 Redis 的高可用性。在安全性方面,需要確保 Redis 部署在受信任的網(wǎng)絡(luò)中,并采取相應(yīng)的網(wǎng)絡(luò)安全措施,例如使用密碼保護(hù) Redis。

因此可以看出,實(shí)際上這種方案也有很大的問(wèn)題,需要謹(jǐn)慎的去使用,總之系統(tǒng)服務(wù)不能假定所有的客戶端都表現(xiàn)的符合預(yù)期。從安全角度講,服務(wù)端必須防范這種來(lái)自客戶端的濫用。

總結(jié)

在單體redis中通過(guò)SETNX + EXPIRE方式可以為多個(gè)JVM加一個(gè)分布式鎖,但是由于操作的非原子性會(huì)導(dǎo)致并發(fā)問(wèn)題,因此出現(xiàn)了幾種原子性解決方法,包括SETNX+時(shí)間value、lua腳本和SET擴(kuò)展命令的方式解決,但是,依然會(huì)出現(xiàn)事務(wù)還沒(méi)完成時(shí)間就失效,產(chǎn)生了新一輪并發(fā),因此,通過(guò)添加一個(gè)看門(mén)狗線程定期檢查能夠解決這個(gè)問(wèn)題,對(duì)于一個(gè)Java開(kāi)發(fā)來(lái)說(shuō)有一個(gè)Redisson框架實(shí)際上封裝了lua腳本來(lái)實(shí)現(xiàn)。
哨兵和主從模式下的分布式redis,如果一個(gè)主機(jī)更新了鎖,但是恰好此時(shí)master發(fā)生了意外,還沒(méi)有同步到slaver,此時(shí)新出現(xiàn)的master沒(méi)有加鎖,依然會(huì)產(chǎn)生問(wèn)題。由此出現(xiàn)了Redlock+Rerdisson的解決方案,但是多個(gè)redis的集群會(huì)帶來(lái)一些性能的損耗,而且由于時(shí)鐘不同步,意外情況的發(fā)生也不能保證這種方案是一定的。

參考鏈接:

https://mp.weixin.qq.com/s/8fdBKAyHZrfHmSajXT_dnA
https://xiaomi-info.github.io/2019/12/17/redis-distributed-lock/
https://juejin.cn/post/6936956908007850014#heading-2
https://zhuanlan.zhihu.com/p/440865954
https://mp.weixin.qq.com/s?__biz=Mzg3NjU3NTkwMQ==&mid=2247505097&idx=1&sn=5c03cb769c4458350f4d4a321ad51f5a&source=41#wechat_redirect

http://www.risenshineclean.com/news/4194.html

相關(guān)文章:

  • 望野小說(shuō)seo包括什么
  • 品牌網(wǎng)站源碼最新網(wǎng)站查詢工具
  • 上海建設(shè)工程信息服務(wù)平臺(tái)湘潭seo快速排名
  • 怎么做百度口碑網(wǎng)站seo優(yōu)化內(nèi)容
  • 旅游網(wǎng)站有哪些功能推廣的公司
  • 網(wǎng)站開(kāi)發(fā)的背景和意義谷歌google play官網(wǎng)下載
  • 政府網(wǎng)站建設(shè) 匯報(bào)高端網(wǎng)站建設(shè)公司
  • 網(wǎng)站建站助手有創(chuàng)意的網(wǎng)絡(luò)廣告案例
  • 邯鄲做網(wǎng)站網(wǎng)絡(luò)公司2023年6月份又封城了
  • 做網(wǎng)站用centos還是ubuntu希愛(ài)力5mg效果真實(shí)經(jīng)歷
  • 高密建設(shè)局網(wǎng)站1688精品貨源網(wǎng)站入口
  • 專業(yè)做網(wǎng)站方案seo標(biāo)題優(yōu)化導(dǎo)師咨詢
  • 兩個(gè)wordpress公用用戶東莞做網(wǎng)站seo
  • 蘇州化妝品網(wǎng)站建設(shè)手機(jī)免費(fèi)建網(wǎng)站
  • 網(wǎng)站建設(shè)做的人多嗎設(shè)計(jì)好看的網(wǎng)站
  • 新余網(wǎng)站設(shè)計(jì)搜外網(wǎng)
  • 畢設(shè)做網(wǎng)站答辯會(huì)要求當(dāng)場(chǎng)演示嗎最基本的網(wǎng)站設(shè)計(jì)
  • 網(wǎng)站建設(shè)怎么收費(fèi)seo網(wǎng)站有哪些
  • 用來(lái)做區(qū)位分析的地圖網(wǎng)站佛山全市核酸檢測(cè)
  • 鄭州做網(wǎng)站建設(shè)的公司今晚比賽預(yù)測(cè)比分
  • git做網(wǎng)站根目錄企業(yè)查詢app
  • 網(wǎng)站開(kāi)發(fā)實(shí)戰(zhàn)教程百度推廣一年收費(fèi)標(biāo)準(zhǔn)
  • 屏蔽收索引擎抓取網(wǎng)站sem競(jìng)價(jià)推廣代運(yùn)營(yíng)收費(fèi)
  • 外貿(mào) 國(guó)外推廣網(wǎng)站模板網(wǎng)站好還是自助建站好
  • 瑤海區(qū)網(wǎng)站建設(shè)中國(guó)關(guān)鍵詞官網(wǎng)
  • 昆明網(wǎng)站開(kāi)發(fā)培訓(xùn)機(jī)構(gòu)整站優(yōu)化加盟
  • 網(wǎng)校網(wǎng)站怎么做網(wǎng)絡(luò)營(yíng)銷課程個(gè)人總結(jié)3000字
  • 浙江省住房建設(shè)廳繼續(xù)教育網(wǎng)站財(cái)經(jīng)新聞每日財(cái)經(jīng)報(bào)道
  • 成都網(wǎng)站建設(shè)服務(wù)平臺(tái)西安專業(yè)網(wǎng)絡(luò)推廣平臺(tái)
  • uc網(wǎng)站怎么做鄭州網(wǎng)絡(luò)營(yíng)銷公司哪個(gè)好