乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      NoSQL之Redis高級

       貪挽懶月 2022-06-20 發(fā)布于廣東

      學(xué)習(xí)一門技術(shù),我們首先得明白以下幾點:

      • 它是什么?

      • 它為什么會出現(xiàn)?

      • 它的出現(xiàn)解決了什么問題?

      • 如何使用?

      帶著這幾個問題去學(xué),我們才能將它的衣服一件件的扒光,最后看到它的本質(zhì)。不然面試的時候面試官稍微問得深入一點就涼涼了。接下來聊聊NoSql。

      一、什么是NoSql?

      NoSql意思是Not Only Sql,不僅僅是SQL。NoSql也被稱作非關(guān)系型數(shù)據(jù)庫,那么與之相對的就是關(guān)系型數(shù)據(jù)庫。你去百度“什么叫關(guān)系型數(shù)據(jù)庫”,搜到的是非常官方的答案,說是依據(jù)關(guān)系模型來創(chuàng)建的數(shù)據(jù)庫??戳税胩?,所有字都認識,但是連在一起就不知道是什么意思了。這里不搞那些花里胡哨的,用最簡單的話說明白:

      • 關(guān)系型數(shù)據(jù)庫:以數(shù)據(jù)表來存儲數(shù)據(jù),一個pojo對應(yīng)一張表,表中的一行就是pojo的一個對象,一列就是對象的一個屬性,表與表之間的關(guān)聯(lián)代表對象之間的一對一、一對多和多對多的關(guān)系。通過Sql對數(shù)據(jù)表中的數(shù)據(jù)進行操作。

      • 非關(guān)系型數(shù)據(jù)庫:上面說明白了關(guān)系型數(shù)據(jù)庫,那么非關(guān)系型數(shù)據(jù)庫就好理解了。沒有那些對應(yīng)關(guān)系,一般是以鍵值對的形式存儲,不需要通過Sql來進行操作。其實NoSql數(shù)據(jù)庫也不是全都用鍵值對的形式存儲數(shù)據(jù),主要有以下四類:

      • 鍵值存儲型(Redis)

      • 文檔型(MongoDB)

      • 列儲存(Hbase)

      • 圖關(guān)系數(shù)據(jù)庫(Neo4J)

      二、NoSql為何會興起?

      在此之間,先來說說互聯(lián)網(wǎng)架構(gòu)的演變(數(shù)據(jù)庫層面)。

      • 單機MySql:互聯(lián)網(wǎng)剛興起的時候,由于使用的人數(shù)不多,一個網(wǎng)站就是我們IDE中的一個工程,然后發(fā)布到服務(wù)器上,數(shù)據(jù)庫也就一個MySql就夠了。

      • 到后來,用的人多了,數(shù)據(jù)的讀取越來越慢,就在數(shù)據(jù)庫的前面擋了一層緩存,dao層訪問的是緩存,而不是直接捅到數(shù)據(jù)庫中取。當(dāng)時緩存用得多的是Memcached。

      • 再后來,數(shù)據(jù)庫的寫入操作越來越多了,由于緩存只能解決讀取壓力,所以它又行不通了。所以就出現(xiàn)了讀寫分離。dao層訪問緩存,緩存連接著主庫和從庫,寫操作在主庫進行,主庫再同步到從庫,讀操作在從庫進行,這樣來達到讀寫分離的目的。

      • 隨著訪問量越來越大,讀寫分離也搞不定了,就出現(xiàn)了分庫分表和數(shù)據(jù)庫集群等技術(shù)。

      • 到今天,互聯(lián)網(wǎng)用戶人數(shù)已經(jīng)不是一般的多了,有海量的數(shù)據(jù),如果要對海量的數(shù)據(jù)進行挖掘,關(guān)系型數(shù)據(jù)庫就不適用了。所以NoSql就閃亮登場了。本文將介紹用得比較多的NoSQL數(shù)據(jù)庫 --- Redis。

      三、NoSQL之Redis

      關(guān)于redis的安裝、五種數(shù)據(jù)類型以及jedis我在之前的文章中有說過,這里來聊聊剩下的內(nèi)容。
      1、發(fā)布與訂閱:

      • 什么是發(fā)布與訂閱:
        發(fā)布與訂閱,就類似于微信公眾號。微信公眾號發(fā)布了一條消息,所有關(guān)注了這個公眾號的人都能夠收到消息。了解過MQ的人也許會問,MQ也有類似的功能,那么它們之間有什么區(qū)別呢?形象地說就是,Redis是兼職,MQ是專職的。MQ它是實現(xiàn)了JMS規(guī)范的專門處理消息的消息中間件,其功能遠比Redis提供的發(fā)布與訂閱強大且復(fù)雜得多,后續(xù)我也會專門說一說MQ,歡迎大家關(guān)注。

      • 怎么用?
        其實特別簡單,新建兩個類,一個訂閱者一個發(fā)布者。發(fā)布者調(diào)用publish方法,指定發(fā)布的channel和消息內(nèi)容,而發(fā)布者只需繼承JedisPubSub類,重寫一些方法(主要是為了能夠打印訂閱情況,為了避免每個訂閱者都重寫這些方法,自己寫一個類去重寫這些方法,然后訂閱者繼承自己這個類就行了),然后調(diào)用subscribe方法,指定訂閱者和channel即可訂閱。代碼如下:
        工具類:

       1public class SubUtil extends JedisPubSub {
      2    @Override
      3    public void onMessage(String channel, String message) {
      4        System.out.println(String.format("receive redis published message, channel %s, message %s", channel, message));
      5    }
      6
      7    @Override
      8    public void onSubscribe(String channel, int subscribedChannels) {
      9        System.out.println(String.format("subscribe redis channel success, channel %s, subscribedChannels %d",
      10                channel, subscribedChannels));
      11    }
      12
      13    @Override
      14    public void onUnsubscribe(String channel, int subscribedChannels) {
      15        System.out.println(String.format("unsubscribe redis channel, channel %s, subscribedChannels %d",
      16                channel, subscribedChannels));
      17    }
      18}

      訂閱者:

       1/**
      2 * 訂閱者(先啟動訂閱者,再啟動發(fā)布者)
      3 */

      4public class SubOne extends SubUtil {
      5    public static void main(String[] args) throws Exception{
      6        Jedis jedis = new Jedis("192.168.x.xx"6379);
      7        SubOne subOne = new SubOne();
      8        jedis.subscribe(subOne, "test");
      9        System.in.read();
      10    }
      11}

      發(fā)布者:

      1public class Pub {
      2    public static void main(String[] args) throws Exception {
      3        Jedis jedis = new Jedis("192.168.2.43",6379);
      4        long result = jedis.publish("test","hello");
      5    }
      6}

      這樣就搞定了發(fā)布與訂閱,注意,先啟動訂閱者,再啟動發(fā)布者。按順序啟動后會看到如下運行結(jié)果:

      運行結(jié)果

      2、管道技術(shù):
      在說管道技術(shù)之前先說說TCP請求響應(yīng)模型。

      • 女朋友:你能給我解釋一下什么是TCP么?

      • 程序員:我開始解釋了:你想聽我解釋一下TCP 么?

      • 女朋友:嗯,我想聽你解釋一下TCP 。

      • 程序員:好的,我會給你解釋一下什么是TCP 。

      • 女朋友:好的,我會聽你解釋一下什么是TCP 。

      • 程序員:你準(zhǔn)備好聽我解釋一下什么是TCP了嗎 ?

      • 女朋友:嗯,我準(zhǔn)備好聽你解釋一下什么是TCP了。

      • 程序員:Ok,那我要開始解釋什么是 TCP 了。大概要 10 秒,20 個字。

      • 女朋友:Ok,我準(zhǔn)備收你那個 10 秒時長,20 個字的解釋了。

      系統(tǒng)提示:抱歉,連接超時了……

      • 女朋友:你能給我解釋一下什么是TCP么?

      • 程序員:我開始解釋了:你想聽我解釋一下TCP 么?
        ……

      以上就是TCP請求響應(yīng)模型(本故事純屬虛構(gòu),程序員哪來的女朋友??)。

      redis其實也是這種請求響應(yīng)模型的服務(wù),客戶端向服務(wù)端發(fā)送一個命令,等待服務(wù)端的返回;服務(wù)端接收到命令進行執(zhí)行,然后將結(jié)果返回給客戶端。在這個回合中,服務(wù)端是接收不了其他命令的。假如一個回合需要250毫秒,即使服務(wù)端一次性能接收100k的請求數(shù),那么1秒鐘也只能處理4個請求。使用管道技術(shù)就可以解決這種問題。使用管道就相當(dāng)于可以并發(fā)處理,客戶端不用等待服務(wù)端的響應(yīng),繼續(xù)發(fā)起下一個請求。

      那么jedis如何使用管道技術(shù)呢?請看下面的代碼:

       1public static void main(String[] args{
      2        Jedis jedis = new Jedis("192.168.X.XX",6379);
      3        // 未使用管道技術(shù)
      4        long start1 = System.currentTimeMillis();
      5        for (int i = 1; i <= 10000; i++) {
      6            jedis.set(UUID.randomUUID().toString(), String.valueOf(i));
      7        }
      8        long end1 = System.currentTimeMillis();
      9        System.out.println("未使用管道技術(shù)插入10000條數(shù)據(jù)耗時:" + (end1 - start1) + "毫秒");
      10
      11        // 使用管道技術(shù)
      12        Pipeline pipeline = jedis.pipelined();
      13        long start2 = System.currentTimeMillis();
      14        for (int i = 1; i <= 10000 ; i++) {
      15            pipeline.set(UUID.randomUUID().toString(), String.valueOf(i));
      16        }
      17        long end2 = System.currentTimeMillis();
      18        System.out.println("使用管道技術(shù)插入10000條數(shù)據(jù)耗時:" + (end2 - start2) + "毫秒");
      19  }

      看運行結(jié)果:

      運行結(jié)果

      不得不說這管道技術(shù)還是有兩把刷子的,這耗時相差將近40倍。

      3、為key設(shè)置過期時間:
      我們寫入redis中的內(nèi)容,可以對key設(shè)置過期時間。設(shè)置key的過期時間,超過時間后,將會自動刪除該key(只有執(zhí)行對key值有影響的操作時才會清除)。設(shè)置過期時間的方法是expire,如下:

      1 jedis.expire("hash",30);

      這就是將"hash"這個key設(shè)置為30秒后過期。
      通過persist方法可以清除過期。

      1jedis.persist("hash");

      這就是將"hash"這個key過期清除掉,也就是相當(dāng)于上面設(shè)置的過期無效了。
      如果對一個設(shè)置了過期時間的key再次設(shè)置過期時間,那么將刷新這個過期時間。比如“hash”這個key我設(shè)置了30秒過期,當(dāng)過了24秒的時候我再次使用expire方法設(shè)置它的過期時間為60秒,那么這個key的離過期又還有60秒的時間。

      4、redis的事務(wù):
      redis的事務(wù),本質(zhì)是一組命令的集合。所有的命令都會序列化,然后按順序串行地執(zhí)行。事務(wù)開啟后,所有的命令先入隊,提交事務(wù)的時候,要么全執(zhí)行,要么全不執(zhí)行。常用命令如下:
      命令|作用
      :-:|:-:
      multi|開啟事務(wù)
      exec|提交事務(wù)
      discard|取消事務(wù)
      watch key…|監(jiān)視一個或多個key,如果事務(wù)提交前這些key被改動,事務(wù)將被打斷
      unwatch|取消對所有key的監(jiān)視
      下面來使用一下事務(wù):

      正常情況

      這種是正常執(zhí)行,如果最后不是exec,而是discard,那就是放棄事務(wù)了。接下來看看下面這種情況:
      事務(wù)中有語法錯誤

      set k3的時候,小手一抖,寫成了sete,最后發(fā)現(xiàn)事務(wù)提交不了,所有的命令都未執(zhí)行。這種就相當(dāng)于java中的編譯時期就報錯了,所以肯定是提交不了的。接下來再看另外一種情況:

      運行時異常

      開啟事務(wù)后set了一個String類型的k1,然后讓其自增,再set其他的key,最后提交。結(jié)果是只有自增的那條命令執(zhí)行報錯,其他的正常執(zhí)行。

      最后來看看事務(wù)中的watch和unwatch命令。watch相當(dāng)于樂觀鎖,如果watch的key在事務(wù)提交前被修改了,那么事務(wù)就會提交失敗,得重新watch,獲取到最新值(watch應(yīng)該在事務(wù)開啟之前)。

      watch

      我開了兩個窗口,watch的k1初始值是100,然后在事務(wù)中改成200,在事務(wù)提交之前,另外一邊將其改成了50,現(xiàn)在提交事務(wù)就會出現(xiàn)如下結(jié)果:

      結(jié)果

      這時候再重新開啟事務(wù)去修改,如果這個過程沒有再被修改,事務(wù)才能提交成功,這就類似于CAS。

      5、redis執(zhí)行txt文件中的命令:
      如果我們需要執(zhí)行的redis命令很多,可以寫到一個txt文件中,然后讀取這個txt文件即可執(zhí)行里面的命令。具體步驟如下:

      • 創(chuàng)建txt文件:例如我在/srv目錄下touch一個redispipedata.txt文件

      • 往文件中寫入redis命令:vim打開txt文件,比如我寫入如下命令:

      1set name tom
      2set age 20
      3set sex man
      4set phone 8008208820
      5set country china
      • 將文件轉(zhuǎn)碼:執(zhí)行如下命令

      1unix2dos redispipedata.txt

      如果找不到命令,yum install 一下即可。

      • 在redis-cli所在的目錄下執(zhí)行如下命令:

      1cat /srv/redispipedata.txt | ./redis-cli

      `
      即可批量執(zhí)行txt文件中的命令了,執(zhí)行后可以看到如下結(jié)果:

      執(zhí)行結(jié)果

      上面介紹了管道技術(shù),其實執(zhí)行txt文件中的命令也可以使用管道技術(shù),前面的步驟都一樣,只不過是執(zhí)行命令改成為:

      1cat /srv/redispipedata.txt | ./redis-cli --pipe

      執(zhí)行成功的話會看到如下結(jié)果:

      執(zhí)行結(jié)果

      6、redis的持久化:
      接觸過redis的童鞋一定聽過RDB和AOF這兩個詞,這是redis持久化的兩種方式,下面就介紹一下RDB和AOF。

      • RDB(redis database)介紹:
        RDB就是在指定時間間隔內(nèi)將redis中的數(shù)據(jù)進行快照存儲,默認情況下會將數(shù)據(jù)寫到dump.rdb文件中。保存RDB文件時redis會fork出一個子進程來操作,所以對redis的性能影響很小。但是,由于是隔一段時間保存一次,所以可能會造成一段時間內(nèi)的數(shù)據(jù)丟失。假如配置的是每個5分鐘保存一次,10點鐘的時候保存了一次,10點零4分的時候redis掛掉了,那么10點到10點零4分這段時間的數(shù)據(jù)就丟失了。

      • AOF(append only file)介紹:
        為什么有了RDB還會出現(xiàn)AOF?就是因為上面說的,10點到10點零4分這段時間的數(shù)據(jù)會丟失,所以AOF就出現(xiàn)了。AOF會記錄redis每次寫操作,追加到aof文件中。當(dāng)redis重啟的時候就會重新執(zhí)行記錄的這些操作來恢復(fù)數(shù)據(jù)。由于每次記錄寫操作都是追加到aof文件中,為了避免AOF文件體積過大,redis還可以對AOF文件進行重寫,也就是去除重復(fù)的操作,重寫完成后,就會立即切換到新的AOF文件,此后的操作都會記錄到新的AOF文件中。用戶可以自己選擇AOF持久化的策略,策略有不同步、每秒鐘同步一次和每次進行寫操作的時候同步。默認是每秒鐘同步一次。所以,采用默認策略的話,最多也就丟失這1秒鐘內(nèi)的寫操作。

      這兩種持久化方式原理其實都是利用了寫時復(fù)制,redis搞出兩個進程,父進程與子進程,RDB方式的時候,子進程以快照形式保存數(shù)據(jù),AOF方式的時候,子進程記錄寫操作。

      • RDB的使用:
        redis默認的持久化方式就是RDB,而且默認開啟。RDB保存方式分為主動保存和被動保存。主動保存就是在redis-cli中輸入save命令即可,被動保存就是在redis.conf中配置一些觸發(fā)條件。在redis-cli下使用

      1config get dir

      命令可以查看dump.rdb文件所在的位置。

      被動保存:
      在redis.conf中,有一項配置叫SNAPSHOTTING,這里就是關(guān)于持久化的一些配置。

      rdb的配置

      這三行配置分別表示:15分鐘內(nèi)改了1次;5分鐘內(nèi)改了10次;1分鐘內(nèi)改了1萬次。只要滿足這三條中的任意一條,就會將數(shù)據(jù)保存到dump.rdb中。(測試的時候可以先刪除掉dump.rdb文件,然后5分鐘內(nèi)讓10個key發(fā)生改變,看看是否重新生成了dump.rdb,然后直接讓redis shutdown,然后重新啟動,keys * 看看之前設(shè)置的key是否還在)。

      主動保存:
      假如你設(shè)置的某個key十分重要,你想設(shè)置完就寫到rdb文件中,那么可以在redis-cli中設(shè)置完后用save命令。

      主動保存
      • AOF的使用:
        在redis.conf中,有一段名叫APPEND ONLY MODE的配置,這就是AOF的配置。

        AOF配置

      可以看到,AOF默認是關(guān)閉的,默認文件名為appendonly.aof。上面說到過AOF有三種同步策略,請看下圖,確實是3種,我不是吹的。

      AOF同步策略

      所以,要使用AOF只需要把上面的no改成yes,然后選擇策略就可以了?,F(xiàn)在的問題是,如果同時存在RDB文件和AOF文件,那么redis啟動的時候根據(jù)誰來恢復(fù)?

      測試的辦法:vim打開appendonly.aof文件,在末尾加上一些亂七八糟的不正確的指令,保存退出。然后再啟動redis,如果redis能夠正常啟動,說明啟動時是優(yōu)先根據(jù)RDB來恢復(fù)的,如果不能正常啟動,說明優(yōu)先根據(jù)AOF來恢復(fù)。接下來就開打:

      同時存在RDB和AOF

      將appendonly.aof亂改一通:

      aof文件

      然后啟動redis:

      啟動redis

      結(jié)果報錯了,說明啟動時優(yōu)先根據(jù)AOF來恢復(fù)數(shù)據(jù)的。AOF文件中有不可執(zhí)行的命令,redis啟動就會報錯,那么怎么修復(fù)呢?不要告訴我你打算手動的去將AOF文件中那些不可執(zhí)行的命令刪掉,萬一你手一抖多刪了怎么辦。我們看看redis的src目錄:

      src目錄

      沒錯,就是這兩個文件,一個是修復(fù)RDB文件的,一個是修復(fù)AOF文件的。在src目錄下執(zhí)行

      1./redis-check-aof --fix appendonly.aof

      就可以修復(fù)了。

      在上面AOF的介紹中提到了會對aof文件進行壓縮重寫,那么什么時候會觸發(fā)重寫呢?看看配置文件中的相關(guān)配置:

      重寫策略

      這兩行配置的意思是:當(dāng)文件大小大于上次rewrite時文件大小的100%且大于64MB時進行重寫。其實如果一個公司如果大規(guī)模使用redis的話,rewrite-min-size 至少3GB起步。

      redis的持久化小總結(jié):
      RDB方式性能更好,但是數(shù)據(jù)完整性不如AOF,所以如果對數(shù)據(jù)完整性要求不高,使用RDB即可;如果對數(shù)據(jù)完整性要求高,那么請同時使用RDB和AOF;如果數(shù)據(jù)量大,使用AOF會進行大量的IO操作,對性能的影響十分明顯,那么就使用接下來要介紹的主從復(fù)制。

      7、redis主從:
      所謂主從,就是主從復(fù)制,主機數(shù)據(jù)更新后自動同步到從機的機制,Master以寫為主,Slave以讀為主。主從可以實現(xiàn)讀寫分離以及容災(zāi)恢復(fù)。主從可以分為三種模式,一主二從、薪火相傳和反客為主(這里的二是泛指,其實是一主n從)。

      (1)、主從之一主二從

      • 首先拷貝三份redis.conf,分別重命名為redismaster.conf、redisslave1.conf和redisslave2.conf。然后要做如下的修改:
        ---- 開啟daemonize yes;
        ---- 設(shè)置pid文件名字,pidfile /var/run/redisxxxx.pid;
        ---- 指定端口,port xxxx;
        ---- 設(shè)置log文件名字,logfile "xxxx.log";
        ---- 設(shè)置dump.rdb文件名字,dbfilename dumpxxxx.rdb。
        (xxxx是端口號,三份配置文件端口可以分別為6379、6380、6381)

      • 修改好三份配置文件,接下來就配置一主二仆。
        首先啟動這三個redis,然后在redis-cli輸入info replication命令,可以看到下圖信息:

        info

      可以看到,目前啟動的三個redis的角色都是master,slave都是0。接下來,在6379的redis中set幾個值,然后在6380和6381的redis中輸入

      1slaveof 127.0.0.1 6379

      接下來你就會發(fā)現(xiàn),6379的redis中set的值在另外兩臺機器中也有。

      一主二仆

      這里我先set 了k1,然后再將6380和6381slaveof 6379的,最后發(fā)現(xiàn)get k1也是可以取到值。說明從機會把主機所有數(shù)據(jù)到拉到從機上,包括監(jiān)視主機之前主機上的數(shù)據(jù)。另外,從機是不能set 值的,讀寫分離,主機負責(zé)寫,從機是不能寫的,在從機set 值會報如下錯誤:

      從機不能寫數(shù)據(jù)

      完成了一主二從的配置,看看下面幾個問題:

      • 主機掛了,從機上位變主機還是原地待命?

        主機掛了

      可以看到,主機掛了,從機還是從機,沒有造反。

      • 主機掛了之后復(fù)活了,需要重新配置主從體系嗎?

        主機復(fù)活

      可以看到,原先的主從體系并沒有土崩瓦解,還可以用。

      • 從機掛了,然后復(fù)活。復(fù)活之后從機還是從機嗎?

        從機掛了

      從機掛了再啟動,從機就不再是從機了,而變成了另外一個master。所以用slaveof命令配置的從機重啟后需要重新配置。

      (2)、主從之薪火相傳:
      上面的一主N從,只有一個boss,所有的小弟都直接跟boss打交道,小弟一多boss也會很累的。所以就有了薪火相傳這種模式。6379是主機,6380認6379做大哥,6381認6380做大哥,就這樣一脈相承。

      薪火相傳

      將6381這臺從機掛在6380下,這就是薪火相傳。

      (3)、主從之反客為主:
      一主二從中說到過,主機掛了,從機原地待命,而反客為主就是主機掛了,從機上位了。要上位的從機執(zhí)行如下命令即可:

      1slaveof no one

      然后將另外一臺從機掛在反客為主的這臺機器下,那么原先的這兩臺從機就變成了一個新的一主一從體系。即使原先的主機回來了,也跟這個一主一從沒關(guān)系了。

      8、哨兵模式:
      上面講了主從的三種模式,那么哨兵又是什么鬼?說白了,哨兵模式就是上面“反客為主”的自動版。上面說的“反客為主”,主機掛了需要手動地將從機設(shè)置為主機,哨兵模式就不需要手動設(shè)置了。哨兵模式相當(dāng)于有一個哨兵在巡邏,一旦發(fā)現(xiàn)主機掛了,就會以投票的方式立即選出新的老大。

      • 用法:首先新建一個名為sentinel.conf的文件,然后vi打開,在里面寫一些配置,用來監(jiān)控主機。配置如下:

      1#監(jiān)控主機,主機名,主機ip,主機端口,1表示投票,誰的票數(shù)多就晉升為主機
      2sentinel monitor host6379 127.0.0.1 6379 1
      3#后臺啟動
      4daemonize yes

      然后啟動哨兵,在redis的src目錄下執(zhí)行如下命令:

      1./redis-sentinel /etc/sentinel.conf

      啟動成功后,再讓主機掛掉,等幾秒鐘,就會發(fā)現(xiàn)已經(jīng)自動選出新的主機了。

      哨兵

      可以看到,主機掛了之后,哨兵自動選出了6381為新的主機,6380也跟著6381混了。如果6379又復(fù)活了,它會繼續(xù)擔(dān)任6380和6381的老大呢還是與6380和6381沒關(guān)系了?還是成了6381的小弟?看圖說話:
      哨兵

      6379不再是主,成為了6381的小弟,6381反客為主成功。

        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多