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

當前位置: 首頁 > news >正文

手機app網(wǎng)站建設seo推廣價格

手機app網(wǎng)站建設,seo推廣價格,wordpress文章加字段,怎么知道這網(wǎng)站是php語言做的Redis實戰(zhàn)篇筆記(七) 文章目錄 Redis實戰(zhàn)篇筆記(七)前言達人探店發(fā)布和查看探店筆記點贊點贊排行榜 好友關注關注和取關共同關注關注推送關注推薦的實現(xiàn) 總結 前言 本系列文章是Redis實戰(zhàn)篇筆記的最后一篇,那么到這里…

Redis實戰(zhàn)篇筆記(七)


文章目錄

  • Redis實戰(zhàn)篇筆記(七)
  • 前言
    • 達人探店
      • 發(fā)布和查看探店筆記
      • 點贊
      • 點贊排行榜
    • 好友關注
      • 關注和取關
      • 共同關注
      • 關注推送
      • 關注推薦的實現(xiàn)
  • 總結


前言

本系列文章是Redis實戰(zhàn)篇筆記的最后一篇,那么到這里Redis實戰(zhàn)篇的內(nèi)容就要結束了,本系列文件涵蓋了Redis作為緩存在實戰(zhàn)項目中的大多數(shù)用法


達人探店

發(fā)布和查看探店筆記

這個兩個功能就是普通的業(yè)務,沒有用到 redis,所以我把他們合到一起了

發(fā)布探店筆記
我們點擊下面的加號就可以發(fā)布一篇探店筆記
image.png
這里的上傳圖片,如果是一般的業(yè)務會上傳到一個文件服務器,但是他這里選擇上傳到了我們的前端服務器
image.png
這個 IMAGE_UPLOAD_DIR 就是前端服務器放圖片的地方,要改成自己所對應的位置
image.png
我們像這樣就寫好了一篇探店筆記,然后我們點發(fā)布,就會跳轉到個人中心,并且在主頁的最后也能看見我們發(fā)布的筆記
image.png
image.png
image.png

我們點擊看我們剛發(fā)布的筆記,會報錯,是因為我們還沒有實現(xiàn)這個功能,我們點擊查看,就可以看到前端訪問的接口,接下來我們就去實現(xiàn)它
image.png

**這就是 查看筆記的方法 ** queryBlogById 是我們要實現(xiàn)的方法, querHotBlog 是代碼已經(jīng)寫好的。由于沒有涉及到 Redis 的操作,這里就不再過多解釋了。

@Resourceprivate IUserService userService;@Overridepublic Result queryHotBlog(Integer current) {// 根據(jù)用戶查詢Page<Blog> page = this.query().orderByDesc("liked").page(new Page<>(current, SystemConstants.MAX_PAGE_SIZE));// 獲取當前頁數(shù)據(jù)List<Blog> records = page.getRecords();// 查詢用戶records.forEach(this::queryBlogUser);return Result.ok(records);}@Overridepublic Result queryBlogById(Long id) {// 1. 查詢blogBlog blog = getById(id);if(blog==null){return Result.fail("筆記不存在");}// 2. 查詢blog有關的用戶queryBlogUser(blog);return Result.ok(blog);}private void queryBlogUser(Blog blog) {Long userId = blog.getUserId();User user = userService.getById(userId);blog.setName(user.getNickName());blog.setIcon(user.getIcon());}

實現(xiàn)后,效果就是這樣了。
image.png

點贊

代碼中實現(xiàn)的點贊是 連續(xù)點贊的功能,但是這樣的功能是不好的,如果有人調用這個接口,一直刷贊,數(shù)據(jù)庫直接就爆了,所以我們要對這個功能進行改造

改造后的需求:

  1. 同一個用戶只能點贊一次,再次點擊則取消點贊
  2. 如果當前用戶已經(jīng)點贊,則點贊按鈕高亮顯示(前端已實現(xiàn),判斷Blog類的 isLike 屬性)

那我們怎樣來標記用戶是否點贊過? 用 Redis 的 set集合可以實現(xiàn),set 集合我們已經(jīng)用了好幾次了,set中的元素是不能重復的,可以用來標記

    @Overridepublic Result likeBlog(Long id) {// 1.獲取登錄用戶Long userId = UserHolder.getUser().getId();// 2.判斷當前登錄用戶是否已經(jīng)點贊Boolean isMember = stringRedisTemplate.opsForSet().isMember(BLOG_LIKED_KEY, userId.toString());// 3.如果未點贊,可以點贊if(BooleanUtil.isFalse(isMember)){// 起始這里我覺得也可以做一個異步任務,利用 Redis的高效性,去實現(xiàn)與用戶的交互// 用異步任務來去修改數(shù)據(jù)庫,感覺 Redis 和 數(shù)據(jù)庫都可以這么來用// 3.1 數(shù)據(jù)庫點贊數(shù)+1boolean isUpdate = update().setSql("liked=liked+1").eq("id", id).update();// 3.2 保存用戶到 Redis的 set 集合if(isUpdate){stringRedisTemplate.opsForSet().add(BLOG_LIKED_KEY,userId.toString());}}else {// 4. 如果已經(jīng)點贊,取消點贊// 4.1 數(shù)據(jù)庫點贊數(shù) -1boolean isUpdate = update().setSql("liked=liked-1").eq("id", id).update();// 4.1 把用戶從Redis的 set 集合移除if(isUpdate){stringRedisTemplate.opsForSet().remove(BLOG_LIKED_KEY,userId.toString());}}return Result.ok();}

點贊排行榜

我們在探店筆記的詳情頁面,應該按照點贊的時間顯示出來,比如最早點贊的 TOP5,形成點贊排行榜
但是我們剛才在實現(xiàn)點贊功能的時候,用的是 set 集合,但 set 集合中的元素是無序的,這就不符合我們的功能,所以我們要換一個數(shù)據(jù)結構,即能保留 set 的無序特點,又會使其中的元素有序,那就是 Redis 的 SortedSet
那接下來,我們就要去改造一下我們之前寫的點贊功能

其實就是把之前用 set 集合的操作 換成 SortSet

    @Overridepublic Result likeBlog(Long id) {// 1.獲取登錄用戶Long userId = UserHolder.getUser().getId();// 2.判斷當前登錄用戶是否已經(jīng)點贊Double score = stringRedisTemplate.opsForZSet().score(BLOG_LIKED_KEY, userId.toString());// 3.如果未點贊,可以點贊if(score==null){// 3.1 數(shù)據(jù)庫點贊數(shù)+1boolean isUpdate = update().setSql("liked=liked+1").eq("id", id).update();// 3.2 保存用戶到 Redis的 set 集合if(isUpdate){stringRedisTemplate.opsForZSet().add(BLOG_LIKED_KEY,userId.toString(),System.currentTimeMillis());}}else {// 4. 如果已經(jīng)點贊,取消點贊// 4.1 數(shù)據(jù)庫點贊數(shù) -1boolean isUpdate = update().setSql("liked=liked-1").eq("id", id).update();// 4.1 把用戶從Redis的 set 集合移除if(isUpdate){stringRedisTemplate.opsForZSet().remove(BLOG_LIKED_KEY,userId.toString());}}return Result.ok();}private void isLiked(Blog blog){// 1.獲取登錄用戶Long userId = UserHolder.getUser().getId();// 2.判斷當前登錄用戶是否已經(jīng)點贊Double score = stringRedisTemplate.opsForZSet().score(BLOG_LIKED_KEY, userId.toString());blog.setIsLike(score!=null);}

**那接下來我們就去實現(xiàn)這個點贊排行榜

@Overridepublic Result queryBlogLikes(Long id) {String key= BLOG_LIKED_KEY+id;// 1. 查詢 top5 的點贊用戶 zrange key 0 4Set<String> top5 = stringRedisTemplate.opsForZSet().range(key, 0, 4);if(top5==null||top5.isEmpty()){return Result.ok(Collections.emptyList());}// 這里用了大量的 stream流來處理集合,不太懂 stream流的朋友可以先去學習一下stream流List<Long> ids = top5.stream().map(Long::valueOf).collect(Collectors.toList());String idStr = StrUtil.join(",", ids);// 這里的 sql,沒有默認的是因為,默認的排序它會按 id 降序排列,不符合我們的需求。List<UserDTO> userDTOS = userService.query().in("id", ids).last("ORDER BY FIELD(id," + idStr + ")").list().stream() // 這里處理一下是脫敏.map(user -> BeanUtil.copyProperties(user, UserDTO.class)).collect(Collectors.toList());return Result.ok(userDTOS);}
// 因為未登錄用戶會獲取 user失敗,所以這里加一下,其實這樣做是不好的,業(yè)務容易亂,以后未登錄
// 用戶要使用的地方肯定還會有,所以建議還是寫在 攔截器里。private void isLiked(Blog blog){// 1.獲取登錄用戶UserDTO user = UserHolder.getUser();if (user==null){return;}Long userId = user.getId();// 2.判斷當前登錄用戶是否已經(jīng)點贊Double score = stringRedisTemplate.opsForZSet().score(BLOG_LIKED_KEY, userId.toString());blog.setIsLike(score!=null);}

至此,達人探店的模塊我們也學完了,在這個模塊,我們主要去使用了 Redis 中關于 set 和 SortedSet 的使用。🤗

好友關注

關注和取關

這個功能也沒有用到 Redis, 也只是簡單的業(yè)務,這里也就簡單的記一下
其實這也是個挺常見的功能,不跟視頻自己也可以手敲出來,這里就只記錄 service層的代碼

 @Overridepublic Result follow(Long followUserId, Boolean isFollow) {Long userId = UserHolder.getUser().getId();// 1.判斷到底是關注還是取關if(isFollow==true){Follow follow = new Follow();follow.setUserId(userId);follow.setFollowUserId(followUserId);save(follow);}else {remove(new QueryWrapper<Follow>().eq("user_id",userId).eq("follow_user_id",followUserId));}return Result.ok();}@Overridepublic Result isFollow(Long followUserId) {Long userId = UserHolder.getUser().getId();// 1.查詢是否關注Integer count = query().eq("user_id", userId).eq("follow_user_id", followUserId).count();return Result.ok(count>0);}

共同關注

其實之后的課程有點為了練這個 Redis 而去開發(fā)的這個功能😢,但還是學完吧,也沒有幾節(jié)了
既然要實現(xiàn) 共同關注,那肯定要 先獲取 兩個用戶的關注列表,然后去求交集,那在 Redis 中 set 集合是可以求交集的,所以我們這次用 set 集合來實現(xiàn)求共同關注的功能。在實現(xiàn)這個功能之前,我們先來實現(xiàn)下面兩段代碼
這兩段 代碼與共同關注沒有什么關系,是用來完善用戶的一些信息

// UserController
// 這個是用來點擊頭像,進入主頁
@GetMapping("{id}")public Result queryUserById(@PathVariable("id") Long userId){User user = userService.getById(userId);if(user==null){return Result.ok();}UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);return Result.ok(userDTO);}
// BlogController
// 這個是進入主頁后,顯示這個博主的博客
@GetMapping("/of/user")public Result queryBlogByUserId(@RequestParam(value = "current",defaultValue = "1")Integer current,@RequestParam("id") Long id){Page<Blog> page = blogService.query().eq("user_id", id).page(new Page<>(current, SystemConstants.MAX_PAGE_SIZE));List<Blog> records = page.getRecords();return Result.ok(records);}

下面我們就來寫共同關注的代碼,首先我們要把之前寫的關注稍微改一下,就是操作完數(shù)據(jù)庫后,把關注列表形成一個 set 添加到 Redis 中。

@Overridepublic Result follow(Long followUserId, Boolean isFollow) {Long userId = UserHolder.getUser().getId();// 1.判斷到底是關注還是取關if(isFollow==true){Follow follow = new Follow();follow.setUserId(userId);follow.setFollowUserId(followUserId);boolean save = save(follow);if(save){stringRedisTemplate.opsForSet().add("follows:"+userId,followUserId.toString());}}else {remove(new QueryWrapper<Follow>().eq("user_id",userId).eq("follow_user_id",followUserId));stringRedisTemplate.opsForSet().remove("follows:"+userId,followUserId.toString());}return Result.ok();}

然后我們來寫 共同關注

@Overridepublic Result followCommons(Long id) {// 這里還是用來一些流操作的,不熟悉的朋友還是建議去看看流。// 其實這里真正要說的也就是求交集了 set 的 intersect命令Long userId = UserHolder.getUser().getId();String key="follows:"+userId;String followedKey="follows:"+id;Set<String> intersect = stringRedisTemplate.opsForSet().intersect(key, followedKey);if(intersect==null||intersect.isEmpty()) return Result.ok(Collections.emptyList());List<Long> ids = intersect.stream().map(Long::valueOf).collect(Collectors.toList());List<UserDTO> users = userService.listByIds(ids).stream().map(user -> BeanUtil.copyProperties(user, UserDTO.class)).collect(Collectors.toList());return Result.ok(users);}

其實上面兩個真的沒有什么太多新的東西,用到的 Redis 的部分也是比較少的,想要學 Redis 的朋友也可以跳過這兩節(jié).

關注推送

關注推送也叫 Feed 流,直譯為 投喂,為用戶持續(xù)的提供 “沉浸式” 的體驗,通過無限下拉獲取新的信息

Feed 流產(chǎn)品有兩種常見模式:

  • TimeLine: 不做內(nèi)容篩選,簡單的按照內(nèi)容發(fā)布時間排序,常用于好友或關注.例如朋友圈
    • 優(yōu)點: 信息全面,不會缺失.并且實現(xiàn)也相對簡單
    • 缺點: 信息噪音較多,用戶不一定感興趣,內(nèi)容獲取效率低
  • 智能排序: 利用智能算法屏蔽掉違規(guī)的,用戶不感興趣的內(nèi)容,推送用戶感興趣的信息來吸引用戶
    • 優(yōu)點: 投喂用戶感興趣信息,用戶粘度高,容易沉迷
    • 缺點: 如果算法不精確,可能起反作用

我們這個 個人頁面,是基于關注的好友來做 Feed 流,因此采用 TIMELine 的模式,該模式的實現(xiàn)有三種

  1. 拉模式
  2. 推模式
  3. 推拉結合

拉模式

每個博主都會有一個發(fā)件箱,當他們發(fā)布消息的時候,都會先發(fā)到他們自己的發(fā)件箱當中,并且都帶上時間戳,然后當有一個用戶下拉刷新它的收件箱的時候,這時候,系統(tǒng)會從這個用戶所關注的博主的發(fā)件箱中拉取信息,然后按時間戳排序.下面這個國就演示了這個過程,但是我們想想,它每下拉一次我們就都要給它拉取一次,并且還要排序,那這樣性能是不是就不是很好,那我們接下來繼續(xù)看 推模式
image.png

推模式

而推模式就與拉模式不太一樣了,每個博主沒有收件箱 了,而是把信息直接發(fā)給粉絲的收件箱,并且在收件箱內(nèi)部排好序,這樣粉絲下來刷新的時間,就直接從收件箱中取就可以了.這樣就彌補了拉模式的效率問題.但是推模式同樣有一個問題,就是如果有一個博主的粉絲很多,那它要給粉絲發(fā)消息就要發(fā)多份,這個數(shù)據(jù)量上來了,系統(tǒng)也沒法承受,那么能不能把 這兩種模式的優(yōu)點結合起來呢,那就是接下的推拉模式了
image.png

推拉模式

在推拉模式中,我們將博主分為 大V 和普通博主,大V的粉絲數(shù)很多,通常幾千萬,而普通博主的粉絲數(shù)就比較少了.
我們也把粉絲分為普通粉絲和活躍粉絲.
對于 大V來說,他的粉絲數(shù)很多,所以肯定不能用推模式,所以就用拉模式.但是對于一些活躍粉絲還是用推模式,因為這些活躍粉絲經(jīng)常取看他們博主的信息,所以效率要高一些,而對于哪些普通粉絲就用拉模式,因為他們對博主的關注也不是很多,所以效率嗎,慢一點也就慢一點了,而對于普通博主來說,他的粉絲數(shù)目沒有那么多,所以用推模式也耗費不少資源.
image.png
下面我們再來對比一下這三種模式的優(yōu)缺點.
image.png
那對于我們這個系統(tǒng),不會有大v,所以我們這采用推模式來實現(xiàn).

關注推薦的實現(xiàn)

需求:

  1. 修改新增探店筆記的業(yè)務,在保存 blog 到數(shù)據(jù)庫的時候,推送的收件箱
  2. 收件箱滿足可以根據(jù)時間戳排序,必須用 Redis 的數(shù)據(jù)結構實現(xiàn)
  3. 查詢收件箱時,可以實現(xiàn)分頁查詢。

我們先來修改新增博客的業(yè)務,這個業(yè)務用到了 Redis的 set結構來作為用戶的收件箱,并把這個博客推送到這個博客的主人的粉絲的收件箱。

 @Overridepublic Result saveBlog(Blog blog) {// 獲取登錄用戶UserDTO user = UserHolder.getUser();blog.setUserId(user.getId());// 保存探店博文boolean isSuccess = save(blog);if(!isSuccess){return Result.fail("新增筆記失敗");}List<Follow> follows = followService.query().eq("follow_user_id", user.getId().toString()).list();for (Follow follow : follows) {//獲取粉絲 idLong userId = follow.getUserId();//推送String key="feeds:"+userId;stringRedisTemplate.opsForZSet().add(key,blog.getId().toString(),System.currentTimeMillis());}// 返回idreturn Result.ok(blog.getId());}

然后我們再來實現(xiàn)粉絲查看自己的收件箱,展示出這個用戶所關注的博主的文章
但是我們這里想一下,這里的分頁還能是傳統(tǒng)的分頁嗎?
我們看下面這條圖,t1時,查詢5條,但是 t2這是又傳過來了一個數(shù)據(jù),t3這時候又查詢5條數(shù)據(jù),從頭開始查的話,會查重一個。這就不是我們想要的,那怎么解決查重,就是滾動查詢
image.png
在滾動查詢的時候
t1 和 t2 都是與上述一樣,但是 t3時刻讀取第二頁,是從上回 的lastId 的下一個開始查的,這樣就避免了查重,但是在 Redis 中如何實現(xiàn)呢,我們可以利用 SortedSet 來實現(xiàn)。
image.png
**SortedSet 中有一條命令是 **
ZREVRANGEBYSCORE 是用 score 來搜索
image.png
其中 max ,min是排序的范圍,max是最大值,min是最小值。WITHSCORES是返回時帶著分數(shù) offset是偏移量,是從最大值的哪一個開始排序,0就是從最大值開始,1就是從最大值的下一個開始。count就是查幾個。

那么我們就可以用時間戳來當分數(shù),最新的時間戳就是最大的分數(shù),排在第一位。第一次的時候可以拿當前時間戳,因為對于當前來說,當前時間戳是最大的,最小值我們不關心,就用 0. 第一次 offset 用0,因為第一次分數(shù)最大的我們也要。
然后往后 max 就應該是上回查詢的最小分數(shù),最小還是0,但是這時的 offset就應該是 1了,因為這次的最小分數(shù)是上一會的最小元素,我們上回已經(jīng)查過了,這次不需要了。所以 offset 要用 1. 具體如下
image.png
但是如果兩個元素的時間戳一樣怎么辦?如果這個用戶關注了很多博主,這些博主可能會在同一時間發(fā)布文章,都會推送到這個用戶的收件箱。我們看下面的圖看一下有什么問題

我們看一下,m7和m6的分數(shù)都是 6,第二次查看的時候還是出現(xiàn)了 6,這是為什么,因為,我們第二次查詢的時候 max 是上回的 min,上回的 min是6,而我們的第二次的 offser 是 1,也就是 從分數(shù)為 6 的下一個開始,那分數(shù)為6 的從上往下 第一個是 m7,第二個是 m6,那可不是要從 m6開始查嘛,所以我們的 offset也要改,就是上一次最小分數(shù)的個數(shù)是多少,我們下一次的 offset就是多少,還是這個我們來開,6有兩個,那第二次我們的 offser 就是 2,分數(shù)為6的第一個是m7,往下移動 2位,不就剛好把 上一次我們查到的 分數(shù)為6的隔過去了嘛、
有的朋友可能這里會有的疑惑,如果我 m5 也是 6,你offset不就是 3了,不就把 m5 也隔過去了?
其實不是這樣的,查重復的,我們只在上一次我們查到的里面查重復,不是對于整個 set 查。下面看效果
image.png

image.png
那思路有了,代碼怎么實現(xiàn)呢,我們先來看接口的規(guī)范

image.png
我們在一次查詢中,就要把 本次的最小時間戳和下一次要用的偏移量算出來,傳給前端,前端下一次再調用這個接口的時候,就用這兩個。下面是具體代碼實現(xiàn)

 @Overridepublic Result queryBlogOfFollow(Long max, Integer offset) {//1. 獲取當前用戶Long userId = UserHolder.getUser().getId();//2. 查詢收件箱 ZREVRANGEBYSCORE key max min LIMIT offset countString key="feeds:"+userId;//3. 解析數(shù)據(jù):blogId,timestamp,offset// 這里的 TypedTuple 是一個元組,里面有你要查的數(shù)據(jù),以及分數(shù)Set<ZSetOperations.TypedTuple<String>> typedTuples = stringRedisTemplate.opsForZSet().reverseRangeByScoreWithScores(key, 0, max, offset, 3);// 非空判斷if(typedTuples==null||typedTuples.isEmpty()){return Result.ok();}//4. 根據(jù)id查詢blogList<Long> ids=new ArrayList<>(typedTuples.size());long minTime=0;int os=1;// 接下來就是算 mintime 和 offset,其實這里我們還是用了一點點小算法,用一個 mintime// 變量來接受最小時間戳,然后每次從元組獲取到時間戳,我們就賦給 mintime,這樣遍歷完// 后,mintime 就是最小的// 然后是 算 offset,這里我們根據(jù) mintime,我們剛才不是說了嘛,遍歷的過程中每獲取一次// time ,就賦給 mintime,那么我們在賦之前,加一步,判斷當前獲取的這個 time 與 mintime//是否相等,相等,就讓 os++,不相等就讓 minTime=time,最后重置 os,到最后 os 一定是// 最小的時間戳的重復次數(shù)。// 其實else 里面 的賦值可以去掉,因為最后還會賦值。for (ZSetOperations.TypedTuple<String> typedTuple : typedTuples) {//4.1 獲取博客idids.add(Long.valueOf(typedTuple.getValue()));long time = typedTuple.getScore().longValue();if(time==minTime){os++;}else {minTime=time;os=1;}minTime = time;}//5. 封裝并返回String idStr = StrUtil.join(",", ids);List<Blog> blogs = query().in("id", ids).last("ORDER BY FIELD(id," + idStr + ")").list();for (Blog blog : blogs) {// 查詢 blog 有關的用戶queryBlogUser(blog);// 查詢blog 是否被點贊isLiked(blog);}ScrollResult scrollResult = new ScrollResult();scrollResult.setList(blogs);scrollResult.setOffset(os);scrollResult.setMinTime(minTime);return Result.ok(scrollResult);}

那么今天關于好友關注這個模塊就學完了,雖然前面的比較簡單,但是最后一個理解起來還是有一定難度的


總結

最后的最后,還是希望Redis實戰(zhàn)篇系列比較可以對大家的學習以及工作有一定的幫助,那我們的實戰(zhàn)篇筆記就到這里撒花完結了,朋友們,我們高級篇再見。

我是Mayphyr,從一點點到億點點,我們下次再見

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

相關文章:

  • 易銷云建站公司成都網(wǎng)站seo推廣
  • 購物網(wǎng)站開發(fā)的意義和目的滄州seo包年優(yōu)化軟件排名
  • 張家界市網(wǎng)站建設設計國外網(wǎng)頁模板
  • 長沙php網(wǎng)站建設深圳網(wǎng)絡營銷推廣
  • 新鄉(xiāng)網(wǎng)站建設服務哪家好上海網(wǎng)絡推廣外包公司
  • wordpress 顯示字體大小seo排名分析
  • 自己做網(wǎng)站在線看pdf網(wǎng)站開發(fā)北京公司
  • wordpress 網(wǎng)站加密印度疫情為何突然消失
  • 中華藝術宮室內(nèi)設計百度seo最成功的優(yōu)化
  • 武漢裝修網(wǎng)站建設搜索優(yōu)化整站優(yōu)化
  • 做互聯(lián)網(wǎng)網(wǎng)站需要什么資質嗎陜西seo排名
  • 專門做衣服的網(wǎng)站互聯(lián)網(wǎng)培訓
  • app外包網(wǎng)站seo推廣的方法
  • 網(wǎng)頁詳情頁設計百度seo推廣首選帝搜軟件
  • 網(wǎng)站編輯及seo招聘點擊器 百度網(wǎng)盤
  • 網(wǎng)站寬度多少合適天津seo優(yōu)化公司
  • 免費做產(chǎn)品宣傳的網(wǎng)站電商培訓機構有哪些哪家比較好
  • 為什么網(wǎng)站要用外鏈seo排名賺app
  • 莆田房產(chǎn)網(wǎng)網(wǎng)站如何做關鍵詞優(yōu)化
  • 受歡迎的邢臺做網(wǎng)站sem推廣和seo的區(qū)別
  • 蘭州兼職做網(wǎng)站站長工具星空傳媒
  • 邯鄲網(wǎng)站建設哪能做網(wǎng)站如何注冊
  • 連云港公司做網(wǎng)站google play store
  • 馬可波羅網(wǎng)站做外貿(mào)網(wǎng)站安全檢測在線
  • WordPress完整安裝包谷歌優(yōu)化師
  • 六安火車站網(wǎng)站網(wǎng)絡推廣seo是什么
  • 大良營銷網(wǎng)站建設信息整站seo排名要多少錢
  • 網(wǎng)站開發(fā)需求清單成都關鍵詞seo推廣平臺
  • 大連專業(yè)模板網(wǎng)站制作外貿(mào)網(wǎng)站推廣怎么做
  • 做租房網(wǎng)站搜索引擎優(yōu)化的目的是對用戶友好