摘要:取消命令對所有的監視。或者這樣登錄打印字符串查看服務是否運行關閉當前連接切換到指定的數據庫數據持久化是一個支持持久化的內存數據庫,需要經常將內存中的數據同步到磁盤來保證持久化。
前言
Remote Dictionary Server(遠程數據的服務),是一種NoSQL技術,是一個基于key-value的高速緩存系統,是目前應用面最廣的緩存系統之一。
Redis實戰 第一部分 基本概念和注意事項 1.1 Redis是什么?Redis:Remote Dictionary Server(遠程數據的服務),是一種NoSQL技術,是一個基于key-value的高速緩存系統,Redis是一個開源的使用ANSI C語言編寫、支持網絡、可基于內存亦可持久化的日志型、Key-Value數據庫,并提供多種語言的API。類似于Memcache,但是支持更復雜的數據結構List,Set,SortedSet等,并且有持久化[1]的功能。
Redis有以下特點:
Redis支持數據的持久化,可以講內存中數據曹村在磁盤中,重啟的時候可以再次加載進行使用。
Redis不僅僅是支持簡單的key-value類型的數據,同事還提供List,Set,Hash等數據結構的存儲。
Redis支持數據的備份,即master-salve模式的數據備份。
1.2 Redis緩存的原理一般場景就是數據緩存服務器,與Memcache的角色保持一致;實質上Redis緩存數據庫服務器在提供的緩存的基礎上,同時提供數據持久化(復制),也就是提供數據庫層面的功能。
實現機制:操作時,操作的內存允許設置同步到磁盤上。
1.3 Redis和Memcache的區別?1.存儲方式:
Memcache吧數據全部存在內存中,斷電或者重啟服務器會掛掉,不可以恢復數據,數據大小不能草果內存大小。
Redis有部分數據在磁盤上,這樣能保證數據的持久化。可以定期保存到磁盤(持久化),內存上的數據丟失后可以通過aof恢復。
2.數據支持類型:
Redis在數據支持上要比Memcache多的多。Redis不僅僅支持簡單的key-value類型的數據,同時還支持List,Set,Hash等數據結構的存儲。
Redis的value最大支持512M,Memcache的value最大支持1M。
3.使用底層模型不同
新版本的Redis直接構建了自己的VM機制,因為一般的系統調用系統函數需要耗費一定的時間去移動和請求,有了自己的VM機制就節省了時間。
Redis是單核運行的,Memcache是多喝運行的。
讀寫速度:Redis的寫速度與Memcache差不多,讀速度Memcache比Redis快。
4.運行的環境不同
RedisRedis只支持Linux上執行,這樣省去了對其他操作系統的支持,可以更好的用于本系統環境的優化。
5.對于兩者的選擇具體看應用場景
如果需要緩存的數據只是key-value這樣簡單的結構時首先考慮Memcache,它是足夠穩定可靠。
如果涉及到存儲,排序等一系列復雜操作時,毫無疑問選擇Redis。
1.4 Redis.conf配置文件說明1.Redis默認不是以守護進程的方式運行,可以通過該配置項修改,使用yes啟用守護進程:daemonize no。
2.當Redis以守護進程方式運行時,Redis默認會把pid寫入/var/run/redis.pid文件,可以通過pidfile制定存儲位置:pidfile /var/run/redis.pid。
3.指定Redis監聽端口,默認端口為6379.
4.綁定的主機地址:bind 127.0.0.1
5.當客戶端閑置多長時間后關閉連接,如果制定為0,表示關閉該功能。timeout 300。
6.指定日志記錄級別,Redis總共支持你四個級別debug、verbose、notice、warning、默認是verbose:loglevel verbose。
7.設置數據庫的數量,默認數據庫為0,可以使用SELECT
8.指定在多長時間內,有多少次更新數據,就將數據同步到數據文件,可以多個條件配合:
save//Redis 默認配置文件提供了三個條件 save 900 1 save 300 10 save 60 10000
分別表示900秒(15分鐘)內有1個更改,300秒(5分鐘)內有10個更高,60秒內有10000個更改。
9.指定本地數據文件名,默認值為dump.rdb:dbfilename dump.rdb
10.指定本地數據庫存放目錄:dir ./
11.設置Redis連接密碼,如果配置了連接密碼,客戶端在連接Redis時需要通過AUTH
12.登錄服務器的狀態:info
1.5 Redis數據備份與恢復備份原理和過程:緩存數據庫服務器 =>緩存數據存儲在內存 =>數據庫存儲在磁盤上 =>執行指令,都是在自動在內存中增加數據,數據備份到指定文件位置 => Redis SAVE 命令用于創建當前數據庫的備份。
save:立即存儲快照(內存數據保存到磁盤中)
bgsave:后臺立即存儲快照(內存數據保存到磁盤中)
1.6 Redis事務處理Redis的事務處理比較簡單。只能保證client發起的事務中的命令可以連續的執行,而且不會插入其他的client命令,當一個client在連接中發出multi命令時,這個連接就進入一個事務的上下文,該連接后續的命令不會執行,而是存放到一個隊列中,當執行exec命令時,redis會順序的執行隊列中的所有命令。如果其中執行出現錯誤,執行正確的不會回滾,不同于關系型數據庫的事務。
1.MULTI標記一個事務塊的開始(開啟)。
2.EXEC執行所以事務塊內的命令。
127.0.0.1:6379> multi Ok 127.0.0.1:6379> set user ak QUEUED 127.0.0.1:6379> set school Tsinghua QUEUED 127.0.0.1:6379> set Class Pking QUEUED 127.0.0.1:6379> exec OK OK OK
3.DISCARD取消事務,放棄執行事務塊內的所以命令。
127.0.0.1:6379> multi Ok 127.0.0.1:6379> set user ak QUEUED 127.0.0.1:6379> set school Tsinghua QUEUED 127.0.0.1:6379> discard OK 127.0.0.1:6379> get user (nil)
4.WATCH key [key ...]監視一個(或多個)key,如果在事務執行之前這個(或這些)key被其他命令所改動,那么事務將被打斷。
127.0.0.1:6379> watch user Ok 127.0.0.1:6379> watch school ok
5.UNWATCH取消WATCH命令對所有key的監視。
1.7 Redis安全連接命令1.設置在客戶端連接是需要指定的密碼(由于redis速度相當的快,一秒鐘可以150K次的密碼嘗試,所以需要設置一個密碼強度很大的密碼)。
設置密碼的方式有兩種:
(1) 使用config set 命令的requirepass 參數,具體格式為config set requirepass “password”。 (2) 配置redis.conf 中設置requirepass屬性,后面為密碼。
輸入認證的方式也有兩種:
(1) 登錄時可以 redis-cli -a password
(2)登錄后使用 auth password
//1.設置密碼:首先需要進入Redis的安裝目錄,然后修改配置文件redis.conf。根據grep命令的結果,使用vi編輯器修改“# requirepass foobared” 為“requirepass aklman”,然后保存退出。 $ grep -n requirepass /etc/redis.conf $ sudo vim /etc/redis.conf //2.重啟redis-server與redis-cli: $ sudo service redis-server restart $ redis-cli > info //沒有權限提示 > auth aklman > info //成功查詢數據 > exit //結果表明第一次info命令失敗,在auth認證之后info命令正常返回。最后退出redis-cli。 //或者這樣登錄: $ redis-cli -a aklman > info
2.ECHO message:打印字符串
3.PING:查看服務是否運行
4.QUIT:關閉當前連接
5.SELECT index:切換到指定的數據庫
1.8 Redis數據持久化aof(Append Only File)Redis是一個支持持久化的內存數據庫,Redis需要經常將內存中的數據同步到磁盤來保證持久化。
Redis支持兩種持久化方式:
1、snapshottingRDB(快照),將數據存放到文件里,默認方式。也就是把內存中的內容,壓縮之后,直接存儲到硬盤中,這種方式在啟動的時候,加載速度非常的快!
是將內存中的數據已快照的方式寫入到二進制文件中,默認文件dump.rdb,可以通過配置設置自動做快照持久化的方式。可配置Redis在n秒內如果超過m個key被修改就自動保存快照。
save 900 1 #900秒有1個keys改變,就會執行持久化 save 300 10 #300秒有10個keys改變,就會執行持久化,改成save 100 6更方便 save 60 10000 #60秒有1w個keys改變,就會執行持久化
優勢:
1.數據庫只包含一個文件,通過文件備份策略,定期配置,恢復系統災難。
2.壓縮文件轉移到其他介質上。
3.性能最大化,Redis開始持久化時,分叉出進程,由進程完成持久化工作,避免服務器進程執行I/O操作,啟動效率高。
劣勢:
1.無法高可用:系統一定在定時持久化之前宕機,數據還沒寫入,數據已經丟失。
通過fock分叉進程完成工作,數據集大的時候,服務器停止幾百毫秒甚至1秒。
總結:
redis是一個內存服務器,我們要操作的數據都存儲在內存里面的。訪問速度是非常的快的,但是我們的數據想要存儲到硬盤,就要持久化。持久化的時候,就有持久化的機制,機制就有快照持久化;這種持久化是通過時間與key的改變來確定的。
默認的配置是非常好的配置,說明被改變的值,在沒有持久化的時候,是在內存里面的。這個時候如果服務器有異常,這些在內存里面的值,都會被清空!如果服務器異常之后,再次啟動,我們就會從持久化的文件里面讀取數據到內存,之前沒有持久化的數據,就在也找不到了。
2、 Append-only file(縮寫為aof),將讀寫操作存放到文件中。
由于快照方式在一定間隔時間做一次,所以如果Redis意外down掉的話,就會丟失最后一次快照后的所有修改。
aof比快照方式有更好的持久化性,是由于使用aof時,redis會將每一個收到的寫命令都通過write函數寫入到文件中當redis啟動時會通過重新執行文件中保存的寫命令來在內存中重新建立整個數據庫的內容。
由于os會在內核中緩存write做的修改,所以可能不是立即寫到磁盤上,這樣aof方式的持久化也還是有可能會丟失一部分數據。可以通過配置文件告訴redis我們想要通過fsync函數強制os寫入到磁盤的時機。
配置文件中的可配置參數:
appendonly yes //啟用aof持久化方式 #appendfsync always //收到寫命令就立即寫入磁盤,最慢,但是保證了數據的完整持久化 appendfsync everysec //每秒中寫入磁盤一次,在性能和持久化方面做了很好的折中 #appendfsync no //完全依賴os,性能最好,持久化沒有保證
參數說明:
always :總是保存執行的命令到我們的文件里面。任何一個的改變,都要保存到我們的文件里面。時時的寫文件,這個就會和IO相關,我們的速度就會變慢。
everysec :每一秒中持久化一次。每一秒有多少改變都進行持久化!就是把我們一秒之內的寫操作,修改操作,寫進我們的文件里面。
no :就是根據我們系統的IO來隨機操作。
每一秒中有600個key被改變,這個時候,如果有異常服務器掛了。我們就失去了600個KEY。
優勢:
1.同步:
每秒同步:異步完成,效率高,一旦系統宕機,修改的數據丟失;
每修改同步:同步持久化,每分鐘發生的變化記錄到磁盤中,效率低,安全;
不同步
2.日志寫入操作追加模式append:系統宕機,不影響存在的內容,寫入一半數據,若系統崩潰,下次啟動redis,redis-check-aof工具解決數據一致性。
3.如果日志過大,自動重寫機制,修改的數據寫入到到磁盤文件,創建新文件,記錄產生的修改命令,重寫切換時,保證數據安全。
4.格式清晰的日志文件,完成數據的重建
劣勢:
對于相同數據文件,相比RDB,AOF文件較大
效率低
總結:對比兩個持久化
快照持久化是把內存中的數據,壓縮之后,直接存儲到硬盤里面的。啟動服務器的時候,直接拷貝到內存就可以直接使用了。
AOF持久化是把我們的操作語句存儲到文件里面,啟動服務器的時候,會執行這些語句,寫在我們的內存里面。寫操作會慢于拷貝!!
AOF可以做到每一秒持久化一次;快照持久化是時間和key的改變來匹配的。
1.9 Redis的主從模式(讀寫分析模式)Redis通過主從模式可以允許多個slave(副) server擁有和master(主) server相同的數據庫副本。從服務器只能讀,不能寫。
1.Redis Replication的工作原理:
Slave與master建立連接,發送sync同步命令。
Master會啟動一個后臺進程,將數據庫快照保存到文件中,同時Master主進程會開始收集新的寫命令并緩存。
后臺完成保存后,就將此文件發送給Slave。
Slave將此文件保存到磁盤上。
原理解讀:
在Slave啟動并連接到Master之后,它將主動發送一個SYNC命令。此后Master將啟動后臺存盤進程,同時收集所有接收到的用于修改數據集的命令,在后臺進程執行完畢后,Master將傳送整個數據庫文件到Slave,以完成一次完全同步。而Slave服務器在接收到數據庫文件數據之后將其存盤并加載到內存中。此后,Master繼續將所有已經收集到的修改命令,和新的修改命令依次傳送給Slaves,Slave將在本次執行這些數據修改命令,從而達到最終的數據同步。
如果Master和Slave之間的鏈接出現斷連現象,Slave可以自動重連Master,但是在連接成功之后,一次完全同步將被自動執行。
總結:
當從服務器連接上主服務器時候,我們的主服務器就會把數據發送給從服務器,這些數據都是二進制,第一次連接的時候,是全量拷貝。
之后主服務器有任何數據的修改,都會發送給從服務器,現在發送都是修改的數據,就叫增量拷貝。
只要主從之間斷開過,再次連接,就會實現一次全量拷貝。
2.Redis Replication的特點:
1.同一個Master可以同步多個Slaves。
2.多個slave可以連接同一個master外,還可以連接到其他的slave(當master重啟后,相連的slave轉變為master)。
3.Slave同樣可以接受其它Slaves的連接和同步請求,這樣可以有效的分載Master的同步壓力。因此我們可以將Redis的Replication架構視為圖結構。
4.Master Server是以非阻塞的方式為Slaves提供服務。所以在Master-Slave同步期間,客戶端仍然可以提交查詢或修改請求。
5.Slave Server同樣是以非阻塞的方式完成數據同步。在同步期間,如果有客戶端提交查詢請求,Redis則返回同步之前的數據。
6.為了分載Master的讀操作壓力,Slave服務器可以為客戶端提供只讀操作的服務,寫服務仍然必須由Master來完成。即便如此,系統的伸縮性還是得到了很大的提高(提高了系統的可伸縮性。)。
7.Master可以將數據保存操作交給Slaves完成,從而避免了在Master中要有獨立的進程來完成此操作。
3.如何配置
最少有兩臺(及以上)服務器
主服務器,端口號:6379;pid文件配置好了;數據目錄也配置好了。
從服務器,端口號:6380;pid文件不能和主服務在一起;數據目錄不能和主服務器在一起。
也就是一句話把主服務器的配置文件拷貝一份到從服務器一份修改文件名及相應配置參數。(slave.conf與主服務器的redis.conf一個目錄里面,端口號是6380,dir /sdata ,appendonly no,再啟動新服務器,檢驗是否啟動成功,連接主服務器的IP地址和端口號 slaveod 127.0.0.1 6379,連接主服務器密碼 masterauth aklman,停止從服務器再啟動,驗證)
總結:在Redis的主從配置中,從服務器是一個只讀的設備。不能寫操作。
第二部分 Redis支持的常用數據類型 2.1 字符串(String)設置一個值:set key value
set name aklman
獲取一個值:get key
get name
同時設置多個值:mset key1 value key2 value
同時獲取多個值:mget key1 key2
刪除值:del key
自增1(值必須是數字):incr key
自增指定的值:incrby key
incrby可以操作的最大范圍:有符號的2^64;而修改Memcache的最大范圍描述是無符號的2^642.2 散列表(Hash)超過Redis在整形最大范圍的時候,繼續自增會報錯;而Memcache在最大值時繼續增加會到0再繼續加。自減也同理,只是把增加數值設定負數即可。Memcache在最小值時繼續向下減依然是最小值。
Redis設置的數和增加的數值可以使用負數,Memcache不能使用負數。增減與上同理。
形式:key => array(field1=>value1,field2=>value2,field3=>value2);value1可以重復,field不能重復。
設置值:hset key field value
hset user name aklman
獲取值:hget key field
hget user name
設定多個值:hmset key field1 value1 field2 value2
hmset student name aklman age 18 sex 1
獲取多個值(字段值的順序可以換):hmget key field1 field2 field3
hash表中設定的字段值是唯一的,如果之前有,就會覆蓋!!
獲取hash標的field和value(獲取所以字段及相應值):hgetall key
獲取hash表里面的field:hkeys key
獲取hash表里面的value的個數:hlen key
刪除hash表里面的field值:hdel key field1 field2
注意:hash表中的操作,必須使用hash的方法來操作,字符串的操作就用字符串的方式,不能混著用。
2.3 列表(List)列表:雙向列表,隊列,堆棧;里面的值是可以重復的。
雙向列表:一邊可以進出,另一邊也可以進出
隊列:只能一邊進入,另一邊彈出,先進先出
堆棧:只有一個口,口先進先出
1.雙向列表:
給一個列表從左(右)邊添加內容:lpush(rpush) Listname value1 value2 value3
查看list的內容:lrange Listname 起始位置(0或者其他) 結束位置(-1表示最后面)
從左(右)邊彈出一個值:lpop(rpop) Listname
查看列表的長度:llen Listname
2.隊列:
給一個列表從左邊添加內容:lpushListname value1 value2 value3
從左邊彈出一個值:lpop Listname
給一個列表從右邊添加內容:rpush Listname value1 value2 value3
從右邊彈出一個值:rpop Listname
3.堆棧
給一個列表從左邊添加內容:lpushListname value1 value2 value3
從左邊彈出一個值:lpop Listname
給一個列表從右邊添加內容:rpush Listname value1 value2 value3
從右邊彈出一個值:rpop Listname
2.4 集合(Set)添加數據:sadd set value1 value2 value3
添加完數據后再想添加數據,可以再sadd setvalue4 value5 value3,發現直插入成功兩個,因為集合不允許values的值重復出現。
查看數據:smembers set
隨機彈出:spop set
為什么集合里面的數據能隨機彈出?原因是集合中的數據是無序的,也就是無序集合有這個特性。隨機彈出多個值:spop set n (n不能超過集合元素數)
查看長度:scard set
交集:sinter setA setB
交集就是它們的共同部分,與數學中學的一個樣
并集:sunion setA setB
重復的內容只顯示一次。
差集:sdiff setA setB
redis里面的差集,是只顯示,第一個集合的內容2.5 有序集合(SortedSet)
添加數據:zadd SortedSetKey number1 value1 number2 value2
查看長度:zcard SortedSetKey
查看有序集合里面的值:zrange SortedSetKey 起始位置 結束位置(-1表示最后的位置)
顯示有序集合排序的編號:zrange SortedSetKey 起始位置 結束位置(-1表示最后的位置) withscores
修改排序號:zincrby SortedSetKey n value1
把value1的排序號改成n(表示數字)
顯示倒序:zrevrange SortedSetKey 起始位置 結束位置(-1表示最后的位置)
顯示帶編號的倒序:zrevrange SortedSetKey 起始位置 結束位置(-1表示最后的位置) withscores
注意:
當插入相同排的值時會覆蓋寫之前數據也就說會number一樣覆蓋value,value一樣覆蓋number。
無序集合與有序集合:里面的值都是唯一的,不可重復。當寫入的值,里面已經有的時候,就直接覆蓋!!
2.6 鍵(Key)1.查看Redis里面有多少個key:keys *
一一列出來,星號是通配符,分左匹配和右匹配,左匹配列出指定字符開頭的key,右匹配列出指定字符結尾的key。
通配符很重要,用Redis的時候,肯定是數據兩特別大,此時要去測試數據,有很多類型的測試數據,都是只能使用一次,使用一次之后就要刪除的,假如這些數據都要存儲在Redis里面的,因此我們就要使用這種操作來刪除不需要的數據。反復此時,測試玩刪除數據之后再測試。
2.幾條常用命令:
//在命令行直接運行命令 redis-cli keys "*" //在命令行刪除內容,指定刪除的key redis-cli del "test" //結合兩個命令實現搜索并且刪除key,這樣寫會報錯,因為keys在執行完成之后,一次性把文檔里面拿給了del,此時,del就認為你文檔里面的值,是一個值,要刪除就會報錯。 redis-cli keys "*" | redis-cli del //解決方式如下,xargs的含義是:當左邊命令結果通過管道的時候,只要有xargs參數,它就是告訴左邊的命令,你執行一條結果,就給我一條結果。左邊在執行的時候,執行一個結果,就立即傳給我們右邊去執行 redis-cli keys "*t" |xargs redis-cli del
思考問題:
1.當我們左邊的查詢內容是10G的時候,它要傳給右邊,需要的內存多少?
占用內存20G,因為使用了xargs參數,就是執行完一個結構就傳給右邊,一個結構可以占10K,傳給右邊也是10K,加起來就是20K。
2.在結合find的使用
當數據左邊查詢(操作)的數據量大的時候,一定使用xargs命令
find /toot/ -name "*php" | xargs ls -l
3.判斷key是否存在:exists key
在Redis服務器里面使用
4.設置過期時間:expire key 20
比如,expire sex 10,時間到了就過期,過期了get sex得不到值
5.查看過期時間:ttl key
6.查看key的類型:type key
7.選擇庫:select 2
默認有16個庫,索引是從0開始的,到15結束,默認庫是0.
每一個庫的數據都是互相獨立的。
8.是在redis的客戶端去ping我們redis的服務端:ping hello
回hello,也就是發什么給服務器,服務器如果在線都會回復你什么。如果沒有在線,那就回復不了。只發ping回pong
9.清空當前庫:flushdb
這個命令一般都不會使用,萬一刪了別人的數據就不好。
10.清空索引的庫:flushall
11.Redis的key命名規范
給key進行設置的時候,一定使用:來作為分隔符。
在項目中,應該給每一個項目都設置多帶帶的前綴來區分不同的項目。如,k122009,hedu2009
Redis是有密碼驗證功能的,可以在服務器端開啟密碼驗證,登錄的時候,就要輸入密碼,auth:密碼。而Memcache服務器是沒有密碼驗證功能的。密碼在redis.conf中設置,設置玩重啟redis(ps -ef | grep redis)。
kill pid號:默認是使用-15參數。就是我們的通知我們主進程,關閉系統。主進程會回收它的資源,然后進行關閉。-9 參數:就是我們強制性把程序關閉。
第三部分 總結和擴展 3.1 Redis其他令總結1.EXISTS and DEL
EXISTS key 判斷一個key是否存在;存在返回 1;否則返回0; DEL key 刪除某個key,或是一系列key;
DEL key1 key2 key3 key4。成功返回1,失敗返回0(key值不存在)。
2.TYPE and KEYS
TYPE key:返回某個key元素的數據類型 ( none:不存在,string:字符,list,set,zset,hash),key不存在返回空。
KEYS key—pattern :返回匹配的key列表 (KEYS foo*:查找foo開頭的keys)
3.RANDOMKEY and CLEAR
RANDOMKEY : 隨機獲得一個已經存在的key,如果當前數據庫為空,則返回空字符串。
CLEAR :清除界面。
4.RENAME and RENAMENX
RENAME oldname newname:改key的名字,新鍵如果存在將被覆蓋 。
RENAMENX oldname newname:更改key的名字,如果newname存在,則更新失敗;
5.DBSIZE
DBSIZE :返回當前數據庫的key的總數
6.CONFIG GET and CONFIG SET
CONFIG GET:用來讀取運行Redis服務器的配置參數。
CONFIG SET:用于更改運行Redis服務器的配置參數。
AUTH : 認證密碼
7.CONFIG RESETSTAT
CONFIG RESETSTAT:重置數據統計報告,通常返回值為"OK"
3.2 PHP操作Redis基本操作PHP操作Redis:使用我們的php客戶端(redis擴展)連接到redis服務器
connect("127.0.0.1",6379); $redis->auth("aklman"); $redis->set("DomainServer","Aklman.com");
就可以在Redis從服務器中看到這條信息了。
3.3 INFO 查詢信息解讀INFO [section] :查詢Redis相關信息。 INFO命令可以查詢Redis幾乎所有的信息,其命令選項有如下:
server: Redis server的常規信息
clients: Client的連接選項
memory: 存儲占用相關信息
persistence: RDB and AOF 相關信息
stats: 常規統計
replication: Master/slave請求信息
cpu: CPU 占用信息統計
cluster: Redis 集群信息
keyspace: 數據庫信息統計
all: 返回所有信息
default: 返回常規設置信息
標注[1] 持久化是指存儲到磁盤,服務器重啟后還可以存在。而存儲到內存中的數據,一重啟服務器就不存在。
參考資料Redis實戰
Aklman的讀書筆記
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/61735.html
閱讀 2645·2021-09-13 10:26
閱讀 1907·2021-09-03 10:28
閱讀 1977·2019-08-30 15:44
閱讀 794·2019-08-29 14:07
閱讀 385·2019-08-29 13:12
閱讀 2143·2019-08-26 11:44
閱讀 2336·2019-08-26 11:36
閱讀 2003·2019-08-26 10:19