1. 程式人生 > >Redis 相關運維操作

Redis 相關運維操作

背景

  Redis作為目前全球最流行的KV儲存,除了使用之外,還需要做好日常的運維工作。關於運維相關的工作,本文從以下方面進行介紹說明(Redis5.0以上):

  • 記憶體方面
  • 客戶端連線方面
  • 工具方面

說明

記憶體方面

說明:第一個值是memory stats提供,第二個值是info memory提供

  • 服務記憶體相關(單位:位元組)

  1. 消耗的最大峰值記憶體
    peak.allocated
    used_memory_peak
  2. 最大分配使用記憶體
    total.allocated
    used_memory
  3. 啟動時消耗的初始記憶體
    startup.allocated
    used_memory_startup
  4. 複製積壓的記憶體
    replication.backlog
    repl_backlog_size
  5. 資料佔用記憶體
    dataset.bytes
    used_memory_dataset
  6. 管理內部資料結構的所有開銷的記憶體
    -- 包括startup.allocated, replication.backlog, clients.slaves, clients.normal, aof.buffer及用於管理Redis鍵空間的內部資料結構的總和
    overhead.total
    used_memory_overhead
  7. 當前和重寫AOF緩衝區記憶體
    aof.buffer
    mem_aof_buffer
  8. 所有副本開銷(輸出和查詢緩衝區,連線上下文)的總記憶體
    clients.slaves
    mem_clients_slaves
  9. 所有客戶端開銷(輸出和查詢緩衝區,連線上下文)的總記憶體
    clients.normal
    mem_clients_normal
  10. Lua指令碼的快取開銷的總記憶體
    lua.caches
    used_memory_lua
  11. 服務記憶體佔用實體記憶體比例
    rss-overhead.ratio
    rss_overhead_ratio

  更多記憶體相關的可以看memory stats和info memory

  • Key記憶體相關:檢視單個key的大小

  1. 命令列檢視
    ① DEBUG OBJECT(redis4.0之前)命令估算key的記憶體使用(欄位serializedlength),但因為相差太大,參考價值不高

    > get b
    "cbd"
    
    > DEBUG OBJECT b
    Value at:0x7f24e2b33d40 refcount:1 encoding:embstr serializedlength:4 lru:445248 lru_seconds_idle:3

    ② MEMORY USAGE [SAMPLES count](redis4.0之後)命令估算key的value實際使用記憶體,不包含key的大小和過期屬性的記憶體佔用

    > get b
    "cbd"
    > MEMORY USAGE b
    (integer) 48

    對於集合的資料型別(除string外), usage子命令採用類似LRU SAMPLES的抽樣方式,預設抽樣5個(count)元素求平均得出實際記憶體佔用,所以計算是近似值。可以指定抽樣的SAMPLES個數,如:生成一個100w個欄位的hash鍵:hkey, 每欄位的value長度是從1~1024位元組的隨機值:

    > hlen hkey    // hkey有100w了欄位,每個欄位的value長度介入1~1024個位元組
    (integer) 1000000
    > MEMORY usage hkey   //預設SAMPLES為5,分析hkey鍵記憶體佔用521588753位元組
    (integer) 521588753
    > MEMORY usage hkey SAMPLES  1000 //指定SAMPLES為1000,分析hkey鍵記憶體佔用617977753位元組
    (integer) 617977753
    > MEMORY usage hkey SAMPLES  10000 //指定SAMPLES為10000,分析hkey鍵記憶體佔用624950853位元組
    (integer) 624950853

    這是使用抽樣求平均的演算法,要想獲取key較精確的記憶體值,就指定更大SAMPLES個數。但並不越大越好,因為memory usage越大其佔用cpu時間分片就大。SAMPLES 為0則會對所有值進行取樣。memory usage時間複雜度,和指定的SAMPLES數有關。

  2. rdb工具分析rdb檔案,獲得某個key的實際使用記憶體
    Redis RDB 分析工具 rdbtools 說明

客戶端連線方面

說明:client 是一個客戶端的操作方法,可以檢視當前ID、當前連線資訊等,具體的命令可以看官網

> client help
 1) CLIENT <subcommand> arg arg ... arg. Subcommands are:
 -- 返回當前的連線ID,可用於kill
 2) ID                     -- Return the ID of the current connection.
 -- 返回當前連線的名字
 3) GETNAME                -- Return the name of the current connection.
 -- Kill 來自某個地址的連線
 4) KILL <ip:port>         -- Kill connection made from <ip:port>.
 -- Kill 連線
 5) KILL <option> <value> [option value ...] -- Kill connections. Options are:
 -- Kill 來自某個地址的連線
 6)      ADDR <ip:port>                      -- Kill connection made from <ip:port>
 -- 按型別Kill連線
 7)      TYPE (normal|master|replica|pubsub) -- Kill connections by type.
 -- Kill通過該使用者身份驗證的連線
 8)      USER <username>   -- Kill connections authenticated with such user.
 -- 跳過Kill當前連線,預設yes
 9)      SKIPME (yes|no)   -- Skip killing current connection (default: yes).
 -- 返回客戶端連線的資訊
10) LIST [options ...]     -- Return information about client connections. Options:
 -- 返回指定型別的客戶端
11)   TYPE (normal|master|replica|pubsub) -- Return clients of specified type.
 -- 暫停所有客戶端<timout>毫秒
12) PAUSE <timeout>        -- Suspend all Redis clients for <timout> milliseconds.
 -- 控制伺服器對當前客戶端的回覆,ON:預設,回覆;OFF:不回覆客;SKIP:跳過回覆
13) REPLY (on|off|skip)    -- Control the replies sent to the current connection.
-- 給當前連線設定名字
14) SETNAME <name>         -- Assign the name <name> to the current connection.
-- 取消指定的被阻止的客戶端 
15) UNBLOCK <clientid> [TIMEOUT|ERROR] -- Unblock the specified blocked client.
-- 客戶端快取啟用key跟蹤
16) TRACKING (on|off) [REDIRECT <id>] [BCAST] [PREFIX first] [PREFIX second] [OPTIN] [OPTOUT]... -- Enable client keys tracking for client side caching.
-- 啟用跟蹤時,返回重定向到的客戶端ID
17) GETREDIR               -- Return the client ID we are redirecting to when tracking is enabled.
-- 啟用跟蹤時,控制在連線執行的下一個命令中對鍵的跟蹤(在連線中設定一個狀態,該狀態僅對下一個命令執行有效)
18) CACHING (YES|NO)     -- Basically the command sets a state in the connection, that is valid only for the next command execution, that will modify the behavior of client tracking.
  • CLIENT ID:返回當前連線的ID
    -- ID值單調遞增,不重複
    > CLIENT ID
    (integer) 701
  • CLIENT GETNAME:返回當前連線由CLIENT SETNAME設定的名字
    > CLIENT GETNAME
    "zjy"
  • CLIENT SETNAME:為當前連線分配一個名字
    -- client list 中的name會顯示
    > CLIENT SETNAME zjy
    OK
  • CLIENT LIST:返回所有連線到伺服器的客戶端資訊和統計資料
    -- 返回所有
    > CLIENT LIST
    id=701 addr=192.168.163.134:52722 fd=16 name=zjy age=1225 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=32742 obl=0 oll=0 omem=0 events=r cmd=client user=default
    id=598 addr=192.168.163.134:36327 fd=12 name= age=9321 idle=1 flags=S db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=replconf user=replica-user
    id=703 addr=192.168.163.1:64583 fd=9 name= age=115 idle=81 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=auth user=dba
    
    -- 返回指定型別:normal|master|replica|pubsub
    > CLIENT LIST type replica
    id=598 addr=192.168.163.134:36327 fd=12 name= age=9341 idle=0 flags=S db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=replconf user=replica-user
    
    -- 返回指定型別:normal|master|replica|pubsub
    > CLIENT LIST type normal
    id=701 addr=192.168.163.134:52722 fd=16 name=zjy age=1254 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=48 qbuf-free=32720 obl=0 oll=0 omem=0 events=r cmd=client user=default
    id=703 addr=192.168.163.1:64583 fd=9 name= age=144 idle=110 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=auth user=dba

    格式如下:

    1. 每個已連線客戶端對應一行(以 LF 分割)
    2. 每行字串由一系列 屬性=值(property=value) 形式的域組成,每個域之間以空格分開。

    各欄位的含義:

    id: 唯一的客戶端ID
    addr: 客戶端的地址和埠
    fd: 套接字所使用的檔案描述符
    age: 以秒計算的已連線時長
    idle: 以秒計算的空閒時長
    flags: 客戶端 flag:
      -- O: 客戶端是 MONITOR 模式下的附屬節點(slave)
      -- S: 客戶端是一般模式下(normal)的附屬節點
      -- M: 客戶端是主節點(master)
      -- x: 客戶端正在執行事務
      -- b: 客戶端正在等待阻塞事件
      -- i: 客戶端正在等待 VM I/O 操作(已廢棄)
      -- d: 一個受監視(watched)的鍵已被修改, EXEC 命令將失敗
      -- c: 在將回復完整地寫出之後,關閉連結
      -- u: 客戶端未被阻塞(unblocked)
      -- U: 通過Unix套接字連線的客戶端
      -- r: 客戶端是隻讀模式的叢集節點
      -- A: 儘可能快地關閉連線
      -- N: 未設定任何 flag
    db: 該客戶端正在使用的資料庫 ID
    sub: 已訂閱頻道的數量
    psub: 已訂閱模式的數量
    multi: 在事務中被執行的命令數量
    qbuf: 查詢緩衝區的長度(位元組為單位, 0 表示沒有分配查詢緩衝區)
    qbuf-free: 查詢緩衝區剩餘空間的長度(位元組為單位, 0 表示沒有剩餘空間)
    obl: 輸出緩衝區的長度(位元組為單位, 0 表示沒有分配輸出緩衝區)
    oll: 輸出列表包含的物件數量(當輸出緩衝區沒有剩餘空間時,命令回覆會以字串物件的形式被入隊到這個佇列裡)
    omem: 輸出緩衝區和輸出列表佔用的記憶體總量
    events: 檔案描述符事件:
      -- r: 客戶端套接字(在事件 loop 中)是可讀的(readable)
      -- w: 客戶端套接字(在事件 loop 中)是可寫的(writeable)
    cmd: 最近一次執行的命令
    user: 連線的使用者
  • CLIENT PAUSE:連線控制,可以將所有客戶端的訪問暫停給定的毫秒數(slaves的互動除外)
    -- 所有客戶端暫停10秒
    > CLIENT PAUSE 10000
    OK

    場景:

    當需要升級一個例項時,管理員可以作如下操作:
    
    使用CLIENT PAUSE 暫停所有客戶端
    等待數秒,讓slaves節點處理完所有來自master的複製命令
    將一個salve節點切換為master
    重配客戶端以來接新的master 節點
  • CLIENT KILL:按不同的屬性關閉連線:如id,user、addr:port
    -- list
    > client list
    id=598 addr=192.168.163.134:36327 fd=12 name= age=23517 idle=0 flags=S db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=replconf user=replica-user
    id=801 addr=192.168.163.134:53810 fd=13 name= age=208 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=32742 obl=0 oll=0 omem=0 events=r cmd=client user=default
    id=803 addr=192.168.163.1:54934 fd=9 name= age=14 idle=14 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=auth user=dba
    id=804 addr=192.168.163.1:54935 fd=14 name= age=10 idle=7 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=client user=default
    
    -- 根據地址屬性kill
    > CLIENT KILL addr 192.168.163.1:54935
    (integer) 1
    
    -- 根據使用者kill
    > CLIENT KILL user dba
    (integer) 1
    
    -- 根據連線型別kill
    > CLIENT KILL type normal
    (integer) 1
    
    -- 是否kill當前操作的連線
    > CLIENT KILL type normal SKIPME no
    (integer) 1

    注意:Redis的單執行緒屬性,不可能在客戶端執行命令時殺掉它. 從客戶端的角度看,永遠無法殺死一個正在執行命令的連線。 但是當客戶端傳送下一條命令時會意識到連線已被關,原因為網路錯誤。

  • CLIENT UNBLOCK:解除客戶端的阻塞
    -- Connection A (blocking connection):
    > CLIENT ID
    2934
    > BRPOP key1 key2 key3 0
    (client is blocked)
    
    ... Now we want to add a new key ...
    
    -- Connection B (control connection):
    > CLIENT UNBLOCK 2934
    1
    
    -- Connection A (blocking connection):
    ... BRPOP reply with timeout ...
    NULL
    
    > BRPOP key1 key2 key3 key4 0
    (client is blocked again)
  • CLIENT REPLY:是否禁用redis伺服器對當前客戶端的回覆響應
    -- 控制伺服器是否將回復客戶端的命令
    ON. 預設選項,回覆客戶端每條命令
    OFF. 不回覆客戶端命令
    SKIP. 跳過該命令的回覆
    
    當執行命令設定為OFF或SKIP,設定命令收不到任何回覆,當設定為 ON時,返回OK
  • CLIENT TRACKING:啟用Redis伺服器的跟蹤功能,該功能用於伺服器的客戶端快取
  • CLIENT CACHING:當在OPTIN或OPTOUT模式下啟用跟蹤時,此命令控制在連線執行的下一個命令中對鍵的跟蹤
    說明:客戶端快取是Redis6.0的一個新功能,利用應用程式伺服器中的可用記憶體,提高效能。CLIENT TRACKING 和CLIENT CACHING是針對客戶端快取進行跟蹤和管理,如果對客戶端快取有興趣的可以看官網說明。
  • HELLO protover [AUTH username password] [SETNAME clientname]:切換協議(RESP2、RESP3)
    -- Redis 6或更高版本支援兩種協議,即舊協議RESP2和新協議RESP3。Redis 6連線以RESP2模式啟動,因此RESP2的客戶端無需更改 想要握手RESP3模式的客戶端需要使用“ 3”作為第一個引數來呼叫HELLO命令。
    > HELLO 3 auth dba dba setname zjy
    1# "server" => "redis"
    2# "version" => "6.0.3"
    3# "proto" => (integer) 3
    4# "id" => (integer) 825
    5# "mode" => "cluster"
    6# "role" => "master"
    7# "modules" => (empty array)
  • COMMAND:以陣列的形式返回有關所有Redis命令的詳細資訊
  • COMMAND COUNT:返回Redis伺服器命令的總數

  • COMMAND GETKEYS:從完整的Redis命令中找到key
    -- 返回key
    > COMMAND GETKEYS MSET a b c d e f
    1) "a"
    2) "c"
    3) "e"
    > COMMAND GETKEYS SORT mylist ALPHA STORE outlist
    1) "mylist"
    2) "outlist"
  • COMMAND INFO command-name [command-name ...]:返回的結果與COMMAND相同,但是你可以指定返回哪些命令
    > COMMAND INFO get set
    1) 1) "get"
       2) (integer) 2
       3) 1~ readonly
          2~ fast
       4) (integer) 1
       5) (integer) 1
       6) (integer) 1
       7) 1~ @read
          2~ @string
          3~ @fast
    2) 1) "set"
       2) (integer) -3
       3) 1~ write
          2~ denyoom
       4) (integer) 1
       5) (integer) 1
       6) (integer) 1
       7) 1~ @write
          2~ @string
          3~ @slow
  • CONFIG RESETSTAT:重置INFO命令統計裡面的一些計算器
  • DEBUG SEGFAULT:模擬錯誤,讓server崩潰
  • LASTSAVE:檢視BGSAVE 命令執行的結果,返回時間戳
    > LASTSAVE
    (integer) 1594473834 
  • SLOWLOG subcommand [argument]:用於讀取和重置Redis慢查詢日誌
    實際執行命令所需的時間:在命令執行過程中執行緒被阻塞且不能同時處理其他請求的階段。
    > config get *slow*
    1) "slowlog-max-len"  -- 慢查詢長度
    2) "128"
    3) "slowlog-log-slower-than"  --慢查詢閾值時間,微妙
    4) "10000"
    > SLOWLOG get 3       -- 檢視慢查詢記錄條數
    (empty array)
    > SLOWLOG len         -- 獲取慢查詢長度
    (integer) 0
    > SLOWLOG reset       -- 重置慢查詢日誌
    OK

工具方面

 redis-cli --help

# /usr/local/redis6.0/bin/redis-cli -h 192.168.163.134 -p 8379 --help
redis-cli 6.0.3

Usage: redis-cli [OPTIONS] [cmd [arg [arg ...]]]
-- 服務地址
  -h <hostname>      Server hostname (default: 127.0.0.1).
-- 服務埠
  -p <port>          Server port (default: 6379).
-- 服務套接字
  -s <socket>        Server socket (overrides hostname and port).
-- 服務密碼
  -a <password>      Password to use when connecting to the server.
                     You can also use the REDISCLI_AUTH environment
                     variable to pass this password more safely
                     (if both are used, this argument takes predecence).
-- ACL設定的使用者
  --user <username>  Used to send ACL style 'AUTH username pass'. Needs -a.
-- ACL設定的密碼
  --pass <password>  Alias of -a for consistency with the new --user option.
-- 強制設定密碼
  --askpass          Force user to input password with mask from STDIN.
                     If this argument is used, '-a' and REDISCLI_AUTH
                     environment variable will be ignored.
-- 服務URI
  -u <uri>           Server URI.
-- 指定執行的命令次數
  -r <repeat>        Execute specified command N times.
-- 間隔多少秒執行指定的命令
  -i <interval>      When -r is used, waits <interval> seconds per command.
                     It is possible to specify sub-second times like -i 0.1.
-- 資料庫號                    
  -n <db>            Database number.
-- RESP協議
  -3                 Start session in RESP3 protocol mode.
-- 讀取標準輸入的最後一個引數
  -x                 Read last argument from STDIN.
-- 分隔符,預設\n
  -d <delimiter>     Multi-bulk delimiter in for raw formatting (default: \n).
-- 開啟叢集模式
  -c                 Enable cluster mode (follow -ASK and -MOVED redirections).
-- 回覆請求格式
  --raw              Use raw formatting for replies (default when STDOUT is
                     not a tty).
-- 格式化輸出              
  --no-raw           Force formatted output even when STDOUT is not a tty.
-- 匯出格式
  --csv              Output in CSV format.
-- 列印伺服器的統計資料
  --stat             Print rolling stats about server: mem, clients, ...
-- 持續取樣延遲模式,在互動式會話中使用此模式,顯示實時統計資訊。 如果指定了--raw或--csv,或者將輸出重定向到非TTY,則它將對延遲進行取樣1秒鐘(可以使用-i更改間隔),然後生成單個輸出並退出
  --latency          Enter a special mode continuously sampling latency.
                     If you use this mode in an interactive session it runs
                     forever displaying real-time stats. Otherwise if --raw or
                     --csv is specified, or if you redirect the output to a non
                     TTY, it samples the latency for 1 second (you can use
                     -i to change the interval), then produces a single output
                     and exits.
-- 像--latency一樣,但是跟蹤延遲隨時間變化。 預設時間間隔是15秒。 使用-i進行更改。
  --latency-history  Like --latency but tracking latency changes over time.
                     Default time interval is 15 sec. Change it using -i.
-- 將延遲顯示為頻譜,需要xterm 256色。 預設時間間隔是1秒。 使用-i進行更改。
  --latency-dist     Shows latency as a spectrum, requires xterm 256 colors.
                     Default time interval is 1 sec. Change it using -i.
-- 模擬工作負載
  --lru-test <keys>  Simulate a cache workload with an 80-20 distribution.
-- 模擬從主接收到的命令的副本
  --replica          Simulate a replica showing commands received from the master.
-- 將遠端服務的RDB轉存到本地
  --rdb <filename>   Transfer an RDB dump from remote server to local file.
-- 將原始Redis協議從stdin傳輸到伺服器
  --pipe             Transfer raw Redis protocol from stdin to server.
-- pipe模式下的超時時間,預設30秒。
  --pipe-timeout <n> In --pipe mode, abort with error if after sending all data.
                     no reply is received within <n> seconds.
                     Default timeout: 30. Use 0 to wait forever.
-- 查詢具有每個型別最多元素的key
  --bigkeys          Sample Redis keys looking for keys with many elements (complexity).
-- 查詢每個型別消耗大量記憶體的key
  --memkeys          Sample Redis keys looking for keys consuming a lot of memory.
--  定義要取樣的key元素的數量    
  --memkeys-samples <n> Sample Redis keys looking for keys consuming a lot of memory.
                     And define number of key elements to sample
--  查詢熱key,在maxmemory-policy為* lfu時有效                
  --hotkeys          Sample Redis keys looking for hot keys.
                     only works when maxmemory-policy is *lfu.
--  使用SCAN命令列出所有鍵                   
  --scan             List all keys using the SCAN command.
--  與scan一起使用以指定掃描模式
  --pattern <pat>    Useful with --scan to specify a SCAN pattern.
-- 執行測試以測量內部系統延遲,測試將執行指定的秒數。
  --intrinsic-latency <sec> Run a test to measure intrinsic system latency.
                     The test will run for the specified amount of seconds.
-- 使用<file>處的Lua指令碼傳送EVAL命令
  --eval <file>      Send an EVAL command using the Lua script at <file>.
-- 與--eval一起使用,啟用Redis Lua偵錯程式
  --ldb              Used with --eval enable the Redis Lua debugger.
-- 與--ldb一樣,但使用同步Lua偵錯程式,在這種模式下,伺服器被阻止,指令碼更改不會從伺服器記憶體中回滾
  --ldb-sync-mode    Like --ldb but uses the synchronous Lua debugger, in
                     this mode the server is blocked and script changes are
                     not rolled back from the server memory.
-- 叢集管理                 
  --cluster <command> [args...] [opts...]
                     Cluster Manager command and arguments (see below).
-- 詳細模式
  --verbose          Verbose mode.
-- 命令列介面上使用密碼時,不顯示警告訊息
  --no-auth-warning  Don't show warning message when using password on command
                     line interface.
  --help             Output this help and exit.
  --version          Output version and exit.

Cluster Manager Commands:
  Use --cluster help to list all available cluster manager commands.

-- 示例 
Examples:
  cat /etc/passwd | redis-cli -x set mypasswd
  redis-cli get mypasswd
  redis-cli -r 100 lpush mylist x
  redis-cli -r 100 -i 1 info | grep used_memory_human:
  redis-cli --eval myscript.lua key1 key2 , arg1 arg2 arg3
  redis-cli --scan --pattern '*:12345*'

  (Note: when using --eval the comma separates KEYS[] from ARGV[] items)

When no command is given, redis-cli starts in interactive mode.
Type "help" in interactive mode for information on available commands
and settings.

注意的引數:

1:--pipe
echo -e "*3\r\n\$3\r\nset\r\n\$8\r\nstring_a\r\n\$3\r\ndba\r\n"  | /usr/local/redis6.0/bin/redis-cli -h 192.168.163.134 -p 9379 --pipe
等同於
echo -e "*3\r\n\$3\r\nset\r\n\$8\r\nstring_a\r\n\$3\r\ndba\r\n" | nc 127.0.0.1 15391

2:--bigkeys
使用scan方式對每個型別的key進行統計,無需擔心對redis造成阻塞,最大key只有string型別是以位元組長度為衡量標準的。list,set,zset等都是以元素個數作為衡量標準,不能說明其佔的記憶體就一定多

3:--memkeys
查詢每個型別消耗大量記憶體的key

4:--hotkeys
需要用LFU才能使用

5:--rdb
匯出遠端的rdb到本地

6:--scan
遍歷所有的key

7:--raw
使用原始格式

8:--cluster
叢集操作

總結

本文大致說明了平時運維的時候需要注意的一些事情,比如記憶體、連線、rdb、key等,後續如果有一些tips,會持續更新到本文當中。