「事件驅動架構」GoldenGate創建從Oracle到Kafka的CDC事件流(2)

2021-01-07 首席架構師智庫

前文:「事件驅動架構」GoldenGate創建從Oracle到Kafka的CDC事件流(1)

步驟7/12:安裝並運行Apache Kafka

從VM的桌面環境中打開Firefox並下載Apache Kafka(我使用的是kafka_2.11-2.1.1.tgz)。

現在,打開一個Linux shell並重置CLASSPATH環境變量(在BigDataLite-4.11虛擬機中設置的當前值會在Kafka中產生衝突):

declare -x CLASSPATH=""

從同一個Linux shell中,解壓縮壓縮包,啟動ZooKeeper和Kafka:

cdtar zxvf Downloads/kafka_2.11-2.1.1.tgzcd kafka_2.11-2.1.1./bin/zookeeper-server-start.sh -daemon config/zookeeper.properties./bin/kafka-server-start.sh -daemon config/server.properties

你可以通過啟動「echo stats | nc localhost 2181」來檢查ZooKeeper是否正常:

[oracle@bigdatalite ~]$ echo stats | nc localhost 2181Zookeeper version: 3.4.5-cdh5.13.1--1, built on 11/09/2017 16:28 GMTClients: /127.0.0.1:34997[1](queued=0,recved=7663,sent=7664) /0:0:0:0:0:0:0:1:17701[0](queued=0,recved=1,sent=0) Latency min/avg/max: 0/0/25Received: 8186Sent: 8194Connections: 2Outstanding: 0Zxid: 0x3fMode: standaloneNode count: 25

您可以檢查Kafka是否與「echo dump | nc localhost 2181 | grep代理」(一個字符串/brokers/ids/0應該出現)

[oracle@bigdatalite ~]$ echo dump | nc localhost 2181 | grep brokers/brokers/ids/0

用於PoC的BigDataLite-4.11虛擬機已經在啟動虛擬機時啟動了一個較老的ZooKeeper實例。因此,請確保禁用了步驟1中描述的所有服務。此外,當您打開一個新的Linux shell時,請注意在啟動ZooKeeper和Kafka之前總是要重置CLASSPATH環境變量,這一點在步驟開始時已經解釋過了。

步驟8/12:為大數據安裝GoldenGate

同樣,從這個頁面下載Oracle GoldenGate for Big Data 12c只需要使用VM中安裝的Firefox瀏覽器(我在Linux x86-64上使用Oracle GoldenGate for Big Data 12.3.2.1.1)。請注意,您需要一個(免費)Oracle帳戶來獲得它。

安裝很容易,只是爆炸壓縮包內的下載:

cd ~/Downloadsunzip OGG_BigData_Linux_x64_12.3.2.1.1.zipcd ..mkdir ogg-bd-poccd ogg-bd-poctar xvf ../Downloads/OGG_BigData_Linux_x64_12.3.2.1.1.tar

就這樣,GoldenGate for Big Data 12c被安裝在/home/oracle/ogg-bd-poc文件夾中。

同樣,BigDataLite-4.11虛擬機已經在/u01/ogg-bd文件夾中安裝了用於大數據的GoldenGate。但它是一個較舊的版本,連接Kafka的選項較少。

步驟9/12:啟動GoldenGate for Big Data Manager

打開大數據大門

cd ~/ogg-bd-poc./ggsci

需要更改管理器埠,否則之前啟動的與GoldenGate (classic)管理器的衝突將被引發。

因此,從大數據的GoldenGate來看,CLI運行:

create subdirsedit params mgr

一個vi實例將開始,只是寫這個內容:

PORT 27801

然後保存內容,退出vi,返回CLI,我們終於可以啟動GoldenGate for Big Data manager監聽埠27081:

步驟10/12:創建數據泵(Data Pump)

現在,我們需要創建在GoldenGate世界中被稱為數據泵的東西。數據泵是一個提取過程,它監視一個跟蹤日誌,並(實時地)將任何更改推到另一個由不同的(通常是遠程的)GoldenGate實例管理的跟蹤日誌。

對於這個PoC,由GoldenGate (classic)管理的trail log aa將被泵送至GoldenGate管理的trail log bb進行大數據處理。

因此,如果您關閉它,請回到來自Linux shell的GoldenGate(經典)CLI:

cd /u01/ogg./ggsci

來自GoldenGate(經典)CLI:

edit params pmpeshop

並在vi中加入以下內容:

EXTRACT pmpeshopUSERIDALIAS ggadminSETENV (ORACLE_SID='orcl')-- GoldenGate for Big Data address/port:RMTHOST localhost, MGRPORT 27801RMTTRAIL ./dirdat/bbPASSTHRU-- The "tokens" part it is useful for writing in the Kafka messages-- the Transaction ID and the database Change Serial NumberTABLE orcl.eshop.*, tokens(txid = @GETENV('TRANSACTION', 'XID'), csn = @GETENV('TRANSACTION', 'CSN'));

保存內容並退出vi。

正如已經解釋的提取器,保存的內容將存儲在/u01/ogg/dirprm/pmpeshop中。人口、難民和移民事務局文件。

現在我們要註冊並啟動數據泵,從GoldenGate CLI:

dblogin useridalias ggadminadd extract pmpeshop, exttrailsource ./dirdat/aa begin nowadd rmttrail ./dirdat/bb extract pmpeshopstart pmpeshop

通過從CLI運行以下命令之一來檢查數據泵的狀態:

info pmpeshopview report pmpeshop

你甚至可以在金門大數據的dirdat文件夾中查看trail log bb是否已經創建:

[oracle@bigdatalite dirdat]$ ls -l ~/ogg-bd-poc/dirdattotal 0-rw-r. 1 oracle oinstall 0 May 30 13:22 bb000000000[oracle@bigdatalite dirdat]$

那檢查泵送過程呢?來自Linux shell:

sqlplus eshop/eshop@ORCL

執行這個SQL腳本創建一個新的模擬客戶訂單:

INSERT INTO CUSTOMER_ORDER (ID, CODE, CREATED, STATUS, UPDATE_TIME)VALUES (CUSTOMER_ORDER_SEQ.NEXTVAL, 'AAAA02', SYSDATE, 'SHIPPING', SYSTIMESTAMP); INSERT INTO CUSTOMER_ORDER_ITEM (ID, ID_CUSTOMER_ORDER, DESCRIPTION, QUANTITY)VALUES (CUSTOMER_ORDER_ITEM_SEQ.NEXTVAL, CUSTOMER_ORDER_SEQ.CURRVAL, 'Inside Out', 1); COMMIT;

現在從GoldenGate(經典)CLI運行:

stats pmpeshop

用於檢查插入操作是否正確計數(在輸出的一部分下面):

GGSCI (bigdatalite.localdomain as ggadmin@cdb/CDB$ROOT) 11> stats pmpeshop Sending STATS request to EXTRACT PMPESHOP ... Start of Statistics at 2019-05-30 14:49:00. Output to ./dirdat/bb: Extracting from ORCL.ESHOP.CUSTOMER_ORDER to ORCL.ESHOP.CUSTOMER_ORDER: *** Total statistics since 2019-05-30 14:01:56 ***Total inserts 1.00Total updates 0.00Total deletes 0.00Total discards 0.00Total operations 1.00

此外,您還可以驗證GoldenGate中存儲的用於測試泵過程的大數據的跟蹤日誌的時間戳。事務提交後,從Linux shell運行:「ln -l ~/og -bd-poc/dirdat」,並檢查最後一個以「bb」作為前綴的文件的時間戳。

步驟11/12:將事務發布到Kafka

最後,我們將在GoldenGate中為BigData創建一個副本流程,以便在Kafka主題中發布泵出的業務事務。replicat將從trail日誌bb讀取事務中的插入、更新和刪除操作,並將它們轉換為JSON編碼的Kafka消息。

因此,創建一個名為eshop_kafkaconnect的文件。文件夾/home/oracle/ogg-bd- pocd /dirprm中的屬性包含以下內容:

# File: /home/oracle/ogg-bd-poc/dirprm/eshop_kafkaconnect.properties# ---- # address/port of the Kafka brokerbootstrap.servers=localhost:9092acks=1 #JSON Converter Settingskey.converter=org.apache.kafka.connect.json.JsonConverterkey.converter.schemas.enable=falsevalue.converter=org.apache.kafka.connect.json.JsonConvertervalue.converter.schemas.enable=false #Adjust for performancebuffer.memory=33554432batch.size=16384linger.ms=0 # This property fix a start-up error as explained by Oracle Support here:# https://support.oracle.com/knowledge/Middleware/2455697_1.htmlconverter.type=key

在同一個文件夾中,創建一個名為eshop_kc的文件。具有以下內容的道具:

# File: /home/oracle/ogg-bd-poc/dirprm/eshop_kc.props# -gg.handlerlist=kafkaconnect #The handler propertiesgg.handler.kafkaconnect.type=kafkaconnectgg.handler.kafkaconnect.kafkaProducerConfigFile=eshop_kafkaconnect.propertiesgg.handler.kafkaconnect.mode=tx #The following selects the topic name based only on the schema namegg.handler.kafkaconnect.topicMappingTemplate=CDC-${schemaName} #The following selects the message key using the concatenated primary keysgg.handler.kafkaconnect.keyMappingTemplate=${primaryKeys} #The formatter propertiesgg.handler.kafkaconnect.messageFormatting=opgg.handler.kafkaconnect.insertOpKey=Igg.handler.kafkaconnect.updateOpKey=Ugg.handler.kafkaconnect.deleteOpKey=Dgg.handler.kafkaconnect.truncateOpKey=Tgg.handler.kafkaconnect.treatAllColumnsAsStrings=falsegg.handler.kafkaconnect.iso8601Format=falsegg.handler.kafkaconnect.pkUpdateHandling=abendgg.handler.kafkaconnect.includeTableName=truegg.handler.kafkaconnect.includeOpType=truegg.handler.kafkaconnect.includeOpTimestamp=truegg.handler.kafkaconnect.includeCurrentTimestamp=truegg.handler.kafkaconnect.includePosition=truegg.handler.kafkaconnect.includePrimaryKeys=truegg.handler.kafkaconnect.includeTokens=true goldengate.userexit.writers=javawriterjavawriter.stats.display=TRUEjavawriter.stats.full=TRUE gg.log=log4jgg.log.level=INFO gg.report.time=30sec # Apache Kafka Classpath# Put the path of the "libs" folder inside the Kafka home pathgg.classpath=/home/oracle/kafka_2.11-2.1.1/libs/* javawriter.bootoptions=-Xmx512m -Xms32m -Djava.class.path=.:ggjava/ggjava.jar:./dirprm

如果關閉,重啟大數據CLI的GoldenGate:

cd ~/ogg-bd-poc./ggsci

and start to create a replicat from the CLI with:

edit params repeshop

in viput this content:

REPLICAT repeshopTARGETDB LIBFILE libggjava.so SET property=dirprm/eshop_kc.propsGROUPTRANSOPS 1000MAP orcl.eshop.*, TARGET orcl.eshop.*;

然後保存內容並退出vi。現在將replicat與trail log bb關聯,並使用以下命令啟動replicat進程,以便從GoldenGate啟動大數據CLI:

add replicat repeshop, exttrail ./dirdat/bbstart repeshop

Check that the replicatis live and kicking with one of these commands:

info repeshopview report repeshop

Now, connect to the ESHOP schema from another Linux shell:

sqlplus eshop/eshop@ORCL

and commit something:

INSERT INTO CUSTOMER_ORDER (ID, CODE, CREATED, STATUS, UPDATE_TIME)VALUES (CUSTOMER_ORDER_SEQ.NEXTVAL, 'AAAA03', SYSDATE, 'DELIVERED', SYSTIMESTAMP); INSERT INTO CUSTOMER_ORDER_ITEM (ID, ID_CUSTOMER_ORDER, DESCRIPTION, QUANTITY)VALUES (CUSTOMER_ORDER_ITEM_SEQ.NEXTVAL, CUSTOMER_ORDER_SEQ.CURRVAL, 'Cars 3', 2); COMMIT;

From the GoldenGate for Big Data CLI, check that the INSERT operation was counted for the replicatprocess by running:

stats repeshop

And (hurrah!) we can have a look inside Kafka, as the Linux shell checks that the topic named CDC-ESHOPwas created:

cd ~/kafka_2.11-2.1.1/bin./kafka-topics.sh --list --zookeeper localhost:2181

and from the same folder run the following command for showing the CDC events stored in the topic:

./kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic CDC-ESHOP --from-beginning

You should see something like:

[oracle@bigdatalite kafka_2.11-2.1.1]$ ./bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic CDC-ESHOP --from-beginning {"table":"ORCL.ESHOP.CUSTOMER_ORDER","op_type":"I","op_ts":"2019-05-31 04:24:34.000327","current_ts":"2019-05-31 04:24:39.637000","pos":"00000000020000003830","primary_keys":["ID"],"tokens":{"txid":"9.32.6726","csn":"13906131"},"before":null,"after":{"ID":11.0,"CODE":"AAAA03","CREATED":"2019-05-31 04:24:34","STATUS":"DELIVERED","UPDATE_TIME":"2019-05-31 04:24:34.929950000"}}{"table":"ORCL.ESHOP.CUSTOMER_ORDER_ITEM","op_type":"I","op_ts":"2019-05-31 04:24:34.000327","current_ts":"2019-05-31 04:24:39.650000","pos":"00000000020000004074","primary_keys":["ID"],"tokens":{"txid":"9.32.6726","csn":"13906131"},"before":null,"after":{"ID":11.0,"ID_CUSTOMER_ORDER":11.0,"DESCRIPTION":"Cars 3","QUANTITY":2}}

For a better output, install jq:

sudo yum -y install jq./kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic CDC-ESHOP --from-beginning | jq .

and here is how will appear the JSON events:

{ "table": "ORCL.ESHOP.CUSTOMER_ORDER", "op_type": "I", "op_ts": "2019-05-31 04:24:34.000327", "current_ts": "2019-05-31 04:24:39.637000", "pos": "00000000020000003830", "primary_keys": [ "ID" ], "tokens": { "txid": "9.32.6726", "csn": "13906131" }, "before": null, "after": { "ID": 11, "CODE": "AAAA03", "CREATED": "2019-05-31 04:24:34", "STATUS": "DELIVERED", "UPDATE_TIME": "2019-05-31 04:24:34.929950000" }}{ "table": "ORCL.ESHOP.CUSTOMER_ORDER_ITEM", "op_type": "I", "op_ts": "2019-05-31 04:24:34.000327", "current_ts": "2019-05-31 04:24:39.650000", "pos": "00000000020000004074", "primary_keys": [ "ID" ], "tokens": { "txid": "9.32.6726", "csn": "13906131" }, "before": null, "after": { "ID": 11, "ID_CUSTOMER_ORDER": 11, "DESCRIPTION": "Cars 3", "QUANTITY": 2 }}

現在打開Kafka -console-consumer.sh進程,並在ESHOP上執行其他一些資料庫事務,以便實時列印發送給Kafka的CDC事件流。

以下是一些用於更新和刪除操作的JSON事件示例:

// Generated with: UPDATE CUSTOMER_ORDER SET STATUS='DELIVERED' WHERE ID=8; { "table": "ORCL.ESHOP.CUSTOMER_ORDER", "op_type": "U", "op_ts": "2019-05-31 06:22:07.000245", "current_ts": "2019-05-31 06:22:11.233000", "pos": "00000000020000004234", "primary_keys": [ "ID" ], "tokens": { "txid": "14.6.2656", "csn": "13913689" }, "before": { "ID": 8, "CODE": null, "CREATED": null, "STATUS": "SHIPPING", "UPDATE_TIME": null }, "after": { "ID": 8, "CODE": null, "CREATED": null, "STATUS": "DELIVERED", "UPDATE_TIME": null }} // Generated with: DELETE CUSTOMER_ORDER_ITEM WHERE ID=3;{ "table": "ORCL.ESHOP.CUSTOMER_ORDER_ITEM", "op_type": "D", "op_ts": "2019-05-31 06:25:59.000916", "current_ts": "2019-05-31 06:26:04.910000", "pos": "00000000020000004432", "primary_keys": [ "ID" ], "tokens": { "txid": "14.24.2651", "csn": "13913846" }, "before": { "ID": 3, "ID_CUSTOMER_ORDER": 1, "DESCRIPTION": "Toy Story", "QUANTITY": 1 }, "after": null}

恭喜你!你完成了PoC:

步驟12/12:使用PoC

GoldenGate中提供的Kafka Connect處理程序有很多有用的選項,可以根據需要定製集成。點擊這裡查看官方文件。

例如,您可以選擇為CDC流中涉及的每個表創建不同的主題,只需在eshop_kc.props中編輯此屬性:

gg.handler.kafkaconnect.topicMappingTemplate=CDC-${schemaName}-${tableName}

更改後重新啟動replicat,從GoldenGate for Big Data CLI:

stop repeshopstart repeshop

您可以在「~/og -bd-poc/AdapterExamples/big-data/kafka_connect」文件夾中找到其他配置示例。

結論

在本文中,我們通過GoldenGate技術在Oracle資料庫和Kafka代理之間創建了一個完整的集成。CDC事件流以Kafka實時發布。

為了簡單起見,我們使用了一個已經全部安裝的虛擬機,但是您可以在不同的主機上免費安裝用於大數據的GoldenGate和Kafka。

請在評論中告訴我您對這種集成的潛力(或限制)的看法。

相關焦點

  • 基於 Flink SQL CDC 的實時數據同步方案
    在異地容災,數據備份等場景中得到廣泛應用,如果是基於查詢的 CDC 有可能導致兩次查詢的中間一部分數據丟失每次 DML 操作均有記錄無需像查詢 CDC 這樣發起全表掃描進行過濾,擁有更高的效率和性能,具有低延遲,不增加資料庫負載的優勢捕獲刪除事件和捕獲舊記錄的狀態,在查詢 CDC 中,周期的查詢無法感知中間數據是否刪除
  • 老朱:Kafka入門教程(1)
    1試想一種需求,網絡爬蟲爬取頁面數據保存到資料庫,為了效率你可能會啟動多個爬蟲一起工作,這個時候你的資料庫可能就吃不消了一直處於爆滿狀態。2為了解決這個問題,你需要把爬蟲數據緩存到一個地方,然後再不急不躁的插入到資料庫中。
  • Kafka Streams開發入門(9)
    功能演示說明這篇文章中我們會創建一個Kafka topic來表示電影打分事件。然後我們編寫一個程序統計每個時間窗口下每部電影接收到的打分人數。我們依然使用ProtocolBuffer對消息事件進行序列化。
  • 我為什麼放棄Kafka,選擇Pulsar?
    資料庫到 Kafka,Kafka Streams 進行分布式流處理,最近使用 KSQL 對 Kafka topic 執行類似 SQL 的查詢等等。Kafka 快速,易於安裝,非常受歡迎,可用於廣泛的範圍或用例。從開發人員的角度來看,儘管 Apache Kafka 一直很友好,但在操作運維方面卻是一團糟。
  • Flume系列 (二)Flume的實際操作--增量寫入Hive--自定義攔截器完成數據過濾--數據傳入kafka消費
    寫在前面: 我是「nicedays」,一枚喜愛做特效,聽音樂,分享技術的大數據開發猿
  • 觀察 | 魔獸「墮落之血」事件與新冠疫情
    「墮落之血」事件(Corrupted Blood incident)是指於2005年出現在網路遊戲「魔獸世界」中會傳染遊戲角色的一種「虛擬瘟疫」。因為意外的大規模傳播,它與現實生活中流行性疾病的相似性也引起了國際性的新聞關注。
  • 黑馬程式設計師:基於oracle資料庫存儲過程的創建及調用
    1.2. 程序結構通過Plsql Developer工具的Test Window 創建 程序模版或者通過語句在SQL Window編寫提示:PLSQL語言的大小寫是不區分的PL/SQL可以分為三個部分:聲明部分、可執行部分、異常處理部分。
  • 4chan:「肯尼·格倫虐貓事件」到「霸凌麥凱·哈奇事件」
    2009年2月15日,名為「glennspam1」的油管用戶在其頻道連續上傳了兩部自拍視頻,幾小時後「匿名者組織」展開復仇.
  • 直播中「周邊」系統的最佳實踐|架構師實踐日
    在 7 月 31 日的上海架構師實踐日中,來自 LeanCloud 研發工程師吳俊,為我們帶來了他們在直播中「周邊」系統的最佳實踐 ,以下是對他演講內容的整理。來來往往的人對應的是觀眾加入聊天室或者離開聊天室的時間通知,這兩種行為在 客戶端的 SDK 中都有事件通知,開發者只要註冊和監聽對應的事件就可以實現一些 UI 的展現。禮物事件可視為一種消息,它與普通消息不同的是,它是類型自定義的消息。因此,開發者只需要修改普通消息的 type 欄位,就可以實現自定義的消息。圖 2 所示,這段代碼定義了一個禮物消息。
  • 北海道「SOS」事件
    然而,這件事之所以吸引我,是因為它具有著「無法名狀」的恐怖感。那種說不清道不明的邏輯線,令人百思不得其解的糾結感,最終都會將你的想像力引向一個你不敢直視的深淵。這起事件,就是被稱為「北海道SOS事件」的一起山難事故。我的讀者們,想必有許多人都去過北海道玩。
  • Oracle Sharding: 雲端分布式關係型資料庫
    體驗教程:https://medium.com/oracledevs/deploying-geo-distributed-oracle-database-on-oracle-cloud-infrastructure-oci-786ad3ec33c6 Oracle Sharding是什麼?
  • 業務變化不息,架構演進不止 第四屆領域驅動設計峰會線上開啟
    Unisys首席應用架構師、全球DDD社區領袖Indu Alagarsamy在分享中認為,DDD與作為軟體技術的消息傳遞進行融合,也就是實現領域驅動設計與事件驅動架構相結合,構建可以隨著業務變化而擴展的可靠系統。
  • 基於大數據的輿情分析系統架構 - 架構篇
    重大輿情事件的實時預警:對於輿情的結果除了正常的搜索和展示需求以外,當有重大事件出現我們需要能做到實時的預警。我們計劃分兩篇介紹完整的輿情新架構,第一篇主要是提供架構設計,會先介紹時下主流的大數據計算架構,並分析一些優缺點,然後引入輿情大數據架構。第二篇會有完整的資料庫表設計和部分示例代碼。大家敬請期待。
  • 限時活動「虛月館殺人事件」舉辦!
    和夏洛克·福爾摩斯一起,體驗在豪華旅店「虛月館」中所展開的,為期七日的殺人事件之謎吧!※本次的活動是附帶劇情內容的短期活動。◆活動參加條件◆僅限完成通關「特異點F 燃燒汙染都市 冬木」的御主參加通關「虛月館殺人事件」的主線任務「其8」,通過投票來推理「虛月館殺人事件」的真兇吧!當大家的推理結論與真兇一致時,主線任務的通關報酬將會發生改變!
  • 《東方新地》「安心事件」女主角(八字解析)
    本文字數:3737,閱讀時長大約5分鐘導讀:命理邏輯詮釋安心事件中的女主角,近期發生的事件。我不太關注娛新聞的,但在香港地區,黃心穎女士「安心事件」太炫目了。透過黃心穎女士八字格局,證明是有「勾引人夫、人盡可夫的交際花」;令人不能不佩服子平八字的精準度和前瞻性。  這則娛樂新聞是來自《東方新地》(2020年2月12日出版) 。
  • 科普:進一步了解 iCloud「照片」、「照片圖庫」和「照片流」
    和朋友和家人分享照片最簡單的方式是開啟「iCloud 照片共享」並創建自己的「共享相簿」或者加入其他人創建的「共享相簿」,這是不同 Apple ID 設備之間同步和推送照片的最佳方式。分享「共享相簿」的前提是要加入到共享相簿的成員組當中,這個過程需要有人發起,收到的人響應才能完成。
  • 「韓寶生」事件啟示
    「韓寶生」是誰?香港網絡上一直流傳著一位名叫「韓寶生」的人,稱他在去年8月31日太子站內的警民衝突事件後失蹤,甚至已經死亡。這些無法得到證實的謠言,不斷被「炒作」,部分人信以為真,更成為抗爭者不斷示威、破壞的一種藉口。
  • 「花與愛麗絲殺人事件」2月20日公映
  • 「牯嶺街少年殺人事件」可怕的不是那一刀,是觀眾的笑聲「上」
    《牯嶺街少年殺人事件》(1991)是楊德昌的創作生涯經典中的經典,電影借一樁1961年的真實少年殺人案(茅武殺人案)為底本,以中學生小四(張震)的故事開展,牽出整個60年代的臺灣社會圖景,慢慢導引至結尾具有毀滅性的一刀。終於在大銀幕看了,那一刀刺死小明後,我覺得頭皮發麻。
  • 由「超跨界」聯名事件引發:Z 世代訪談錄
    在網路遊戲裡開個人演唱會、大牌包跟「小綿羊」捆綁銷售,這些曾經聽上去天方夜譚的「超級跨界事件」卻都真實地發生在現實生活裡:美國說唱歌手 Travis