搜尋
首頁資料庫RedisRedis突然變慢?一起分析如何確定Redis有效能問題以及如何解決

這篇文章為大家帶來了關於Redis的相關知識,遇到Redis延遲過高可能會引發各種問題,下面我們就一起來分析一下如何確定Redis有效能問題和解決方案,希望對大家有幫助。

Redis突然變慢?一起分析如何確定Redis有效能問題以及如何解決

推薦學習:Redis教學

Redis 通常是我們業務系統中一個重要的元件,例如:快取、帳號登錄資訊、排行榜等。

一旦 Redis 請求延遲增加,可能就會導致業務系統「雪崩」。

我在單身紅娘婚戀類型網路公司工作,在雙十一推出下單就送女友的活動。

誰曾想,凌晨 12 點之後,用戶量暴增,出現了一個技術故障,用戶無法下單,當時老大火冒三丈!

經過查找發現 Redis 報 Could not get a resource from the pool#。

取得不到連線資源,且叢集中的單一 Redis 連線量很高。

大量的流量沒了 Redis 的快取回應,直接打到了 MySQL,最後資料庫也宕機了…

於是各種更改最大連線數、連線等待數,雖然報錯訊息頻率有所緩解,但還是持續報錯。

後來經過離線測試,發現存放 Redis 中的字元資料很大,平均 1s 回傳資料。

可以發現,一旦 Redis 延遲過高,就會引發各種問題。

今天跟大家一起來分析下如何確定 Redis 有效能問題和解決方案。

Redis 效能出問題了麼?

最大延遲是客戶端發出指令到客戶端收到指令的回應的時間,正常情況下 Redis 處理的時間極短,在微秒等級。

當 Redis 出現效能波動的時候,例如達到幾秒到十幾秒,這很明顯我們可以認定 Redis 效能變慢了。

有的硬體配置比較高,當延遲 0.6ms,我們可能就認定變慢了。硬體比較差的可能 3 ms 我們才認為有問題。

那我們該如何定義 Redis 真的變慢了呢?

所以,我們需要對目前環境的 Redis 基準表現做測量,也就是在一個系統在低壓力、無幹擾情況下的基本表現。

當你發現 Redis 運作時的延遲是基線表現的 2 倍以上,就可以判定 Redis 表現變慢了。

延遲基準測量

redis-cli 指令提供了–intrinsic-latency 選項,用來監控和統計測試期間內的最大延遲(以毫秒為單位),這個延遲可以作為 Redis 的基線表現。

redis-cli --latency -h `host` -p `port`

例如執行以下指令:

redis-cli --intrinsic-latency 100
Max latency so far: 4 microseconds.
Max latency so far: 18 microseconds.
Max latency so far: 41 microseconds.
Max latency so far: 57 microseconds.
Max latency so far: 78 microseconds.
Max latency so far: 170 microseconds.
Max latency so far: 342 microseconds.
Max latency so far: 3079 microseconds.
45026981 total runs (avg latency: 2.2209 microseconds / 2220.89 nanoseconds per run).
Worst run took 1386x longer than the average latency.

注意:參數100是測試將執行的秒數。我們運行測試的時間越長,我們就越有可能發現延遲峰值。

通常運行 100 秒通常是合適的,足以發現延遲問題了,當然我們可以選擇不同時間運行幾次,避免誤差。

運行的最大延遲是 3079 微秒,所以基線效能是 3079 (3 毫秒)微秒。

要注意的是,我們要在 Redis 的服務端運行,而不是客戶端。這樣,可以避免網路對基線效能的影響。

可以透過 -h host -p port 來連接服務端,如果想要監控網路對 Redis 的效能影響,則可使用 Iperf 測量用戶端對服務端的網路延遲。

如果網路延遲幾百毫秒,表示網路可能有其他大流量的程式在運作導致網路擁塞,需要找運維協調網路的流量分配。

慢指令監控

如何判斷是否為慢指令?

看操作複雜度是否是O(N)。官方文件對每個指令的複雜度都有介紹,盡可能使用O(1) 和 O(log N)指令。

涉及集合運算的複雜度一般為O(N),例如集合全量查詢HGETALL、SMEMBERS,以及集合的聚合運算:SORT、LREM、 SUNION等。

有監控資料可以觀測呢?程式碼不是我寫的,不知道有沒有人用了慢指令。

有兩種方式可以檢查到:

  • 使用 Redis 慢日誌功能找出慢指令;

  • latency-monitor(延遲監控)工具。

此外,可以使用自己(top、htop、prstat 等)快速檢查 Redis 主流程的 CPU 消耗。如果 CPU 使用率很高且流量不高,通常表示使用了慢速指令。

慢日志功能

Redis 中的 slowlog 命令可以让我们快速定位到那些超出指定执行时间的慢命令,默认情况下命令若是执行时间超过 10ms 就会被记录到日志。

slowlog 只会记录其命令执行的时间,不包含 io 往返操作,也不记录单由网络延迟引起的响应慢。

我们可以根据基线性能来自定义慢命令的标准(配置成基线性能最大延迟的 2 倍),调整触发记录慢命令的阈值。

可以在 redis-cli 中输入以下命令配置记录 6 毫秒以上的指令:

redis-cli CONFIG SET slowlog-log-slower-than 6000

也可以在 Redis.config 配置文件中设置,以微秒为单位。

想要查看所有执行时间比较慢的命令,可以通过使用 Redis-cli 工具,输入 slowlog get 命令查看,返回结果的第三个字段以微秒位单位显示命令的执行时间。

假如只需要查看最后 2 个慢命令,输入 slowlog get 2 即可。

示例:获取最近2个慢查询命令

127.0.0.1:6381> SLOWLOG get 2
1) 1) (integer) 6
   2) (integer) 1458734263
   3) (integer) 74372
   4) 1) "hgetall"
      2) "max.dsp.blacklist"
2) 1) (integer) 5
   2) (integer) 1458734258
   3) (integer) 5411075
   4) 1) "keys"
      2) "max.dsp.blacklist"

以第一个 HGET 命令为例分析,每个 slowlog 实体共 4 个字段:

  • 字段 1:1 个整数,表示这个 slowlog 出现的序号,server 启动后递增,当前为 6。

  • 字段 2:表示查询执行时的 Unix 时间戳。

  • 字段 3:表示查询执行微秒数,当前是 74372 微秒,约 74ms。

  • 字段 4: 表示查询的命令和参数,如果参数很多或很大,只会显示部分参数个数。当前命令是hgetall max.dsp.blacklist。

Latency Monitoring

Redis 在 2.8.13 版本引入了 Latency Monitoring 功能,用于以秒为粒度监控各种事件的发生频率。

启用延迟监视器的第一步是设置延迟阈值(单位毫秒)。只有超过该阈值的时间才会被记录,比如我们根据基线性能(3ms)的 3 倍设置阈值为 9 ms。

可以用 redis-cli 设置也可以在 Redis.config 中设置;

CONFIG SET latency-monitor-threshold 9

工具记录的相关事件的详情可查看官方文档:https://redis.io/topics/latency-monitor

如获取最近的 latency

127.0.0.1:6379> debug sleep 2
OK
(2.00s)
127.0.0.1:6379> latency latest
1) 1) "command"
   2) (integer) 1645330616
   3) (integer) 2003
   4) (integer) 2003

事件的名称;

事件发生的最新延迟的 Unix 时间戳;

毫秒为单位的时间延迟;

该事件的最大延迟。

如何解决 Redis 变慢?

Redis 的数据读写由单线程执行,如果主线程执行的操作时间太长,就会导致主线程阻塞。

一起分析下都有哪些操作会阻塞主线程,我们又该如何解决?

网络通信导致的延迟

客户端使用 TCP/IP 连接或 Unix 域连接连接到 Redis。1 Gbit/s 网络的典型延迟约为 200 us。

redis 客户端执行一条命令分 4 个过程:

发送命令-〉 命令排队 -〉 命令执行-〉 返回结果

这个过程称为 Round trip time(简称 RTT, 往返时间),mget mset 有效节约了 RTT,但大部分命令(如 hgetall,并没有 mhgetall)不支持批量操作,需要消耗 N 次 RTT ,这个时候需要 pipeline 来解决这个问题。

Redis pipeline 将多个命令连接在一起来减少网络响应往返次数。

Redis突然變慢?一起分析如何確定Redis有效能問題以及如何解決

redis-pipeline

慢指令导致的延迟

根据上文的慢指令监控查询文档,查询到慢查询指令。可以通过以下两种方式解决:

比如在 Cluster 集群中,将聚合运算等 O(N) 操作运行在 slave 上,或者在客户端完成。

使用高效的命令代替。使用增量迭代的方式,避免一次查询大量数据,具体请查看SCAN、SSCAN、HSCAN和ZSCAN命令。

除此之外,生产中禁用KEYS 命令,它只适用于调试。因为它会遍历所有的键值对,所以操作延时高。

Fork 生成 RDB 导致的延迟

生成 RDB 快照,Redis 必须 fork 后台进程。fork 操作(在主线程中运行)本身会导致延迟。

Redis 使用操作系统的多进程写时复制技术 COW(Copy On Write) 来实现快照持久化,减少内存占用。

Redis突然變慢?一起分析如何確定Redis有效能問題以及如何解決

写时复制技术保证快照期间数据可修改

但 fork 会涉及到复制大量链接对象,一个 24 GB 的大型 Redis 实例需要 24 GB / 4 kB * 8 = 48 MB 的页表。

执行 bgsave 时,这将涉及分配和复制 48 MB 内存。

此外,从库加载 RDB 期间无法提供读写服务,所以主库的数据量大小控制在 2~4G 左右,让从库快速的加载完成。

内存大页(transparent huge pages)

常规的内存页是按照 4 KB 来分配,Linux 内核从 2.6.38 开始支持内存大页机制,该机制支持 2MB 大小的内存页分配。

Redis 使用了 fork 生成 RDB 做持久化提供了数据可靠性保证。

当生成 RDB 快照的过程中,Redis 采用**写时复制**技术使得主线程依然可以接收客户端的写请求。

也就是当数据被修改的时候,Redis 会复制一份这个数据,再进行修改。

采用了内存大页,生成 RDB 期间,即使客户端修改的数据只有 50B 的数据,Redis 需要复制 2MB 的大页。当写的指令比较多的时候就会导致大量的拷贝,导致性能变慢。

使用以下指令禁用 Linux 内存大页即可:

echo never > /sys/kernel/mm/transparent_hugepage/enabled

swap:操作系统分页

当物理内存(内存条)不够用的时候,将部分内存上的数据交换到 swap 空间上,以便让系统不会因内存不够用而导致 oom 或者更致命的情况出现。

当某进程向 OS 请求内存发现不足时,OS 会把内存中暂时不用的数据交换出去,放在 SWAP 分区中,这个过程称为 SWAP OUT。

当某进程又需要这些数据且 OS 发现还有空闲物理内存时,又会把 SWAP 分区中的数据交换回物理内存中,这个过程称为 SWAP IN。

内存 swap 是操作系统里将内存数据在内存和磁盘间来回换入和换出的机制,涉及到磁盘的读写。

触发 swap 的情况有哪些呢?

对于 Redis 而言,有两种常见的情况:

Redis 使用了比可用内存更多的内存;

与 Redis 在同一机器运行的其他进程在执行大量的文件读写 I/O 操作(包括生成大文件的 RDB 文件和 AOF 后台线程),文件读写占用内存,导致 Redis 获得的内存减少,触发了 swap。

我要如何排查是否因为 swap 导致的性能变慢呢?

Linux 提供了很好的工具来排查这个问题,所以当怀疑由于交换导致的延迟时,只需按照以下步骤排查。

获取 Redis 实例 pid

$ redis-cli info | grep process_id
process_id:13160

进入此进程的 /proc 文件系统目录:

cd /proc/13160

在这里有一个 smaps 的文件,该文件描述了 Redis 进程的内存布局,运行以下指令,用 grep 查找所有文件中的 Swap 字段。

$ cat smaps | egrep '^(Swap|Size)'
Size:                316 kB
Swap:                  0 kB
Size:                  4 kB
Swap:                  0 kB
Size:                  8 kB
Swap:                  0 kB
Size:                 40 kB
Swap:                  0 kB
Size:                132 kB
Swap:                  0 kB
Size:             720896 kB
Swap:                 12 kB

每行 Size 表示 Redis 实例所用的一块内存大小,和 Size 下方的 Swap 对应这块 Size 大小的内存区域有多少数据已经被换出到磁盘上了。

如果 Size == Swap 则说明数据被完全换出了。

可以看到有一个 720896 kB 的内存大小有 12 kb 被换出到了磁盘上(仅交换了 12 kB),这就没什么问题。

Redis 本身会使用很多大小不一的内存块,所以,你可以看到有很多 Size 行,有的很小,就是 4KB,而有的很大,例如 720896KB。不同内存块被换出到磁盘上的大小也不一样。

敲重点了

如果 Swap 一切都是 0 kb,或者零星的 4k ,那么一切正常。

当出现百 MB,甚至 GB 级别的 swap 大小时,就表明,此时,Redis 实例的内存压力很大,很有可能会变慢。

解决方案

增加机器内存;

將 Redis 放在單獨的機器上運行,避免在同一台機器上運行需要大量內存的進程,從而滿足 Redis 的內存需求;

增加 Cluster 集群的數量分擔數據量,從而減少每個實例所需的記憶體。

AOF 和磁碟 I/O 導致的延遲

為了確保資料可靠性,Redis 使用 AOF 和 RDB 快照快速復原和持久化。

可以使用 appendfsync 配置將 AOF 配置為以三種不同的方式在磁碟上執行 write 或 fsync (可以在運行時使用 CONFIG SET命令修改此設置,例如:redis 。

  • no:Redis 不執行 fsync,唯一的延遲來自於 write 調用,write 只需要把日誌記錄寫到核心緩衝區就可以返回。

  • everysec:Redis 每秒執行一次 fsync。使用後台子執行緒非同步完成 fsync 操作。最多遺失 1s 的資料。

  • always:每次寫入作業都會執行 fsync,然後用 OK 程式碼回覆客戶端(實際上 Redis 會嘗試將同時執行的許多指令聚集到單一 fsync 中),沒有資料遺失。在這種模式下,效能通常非常低,強烈建議使用快速磁碟和可以在短時間內執行 fsync 的檔案系統實作。

我們通常將 Redis 用於緩存,資料遺失完全惡意從資料獲取,且不需要很高的資料可靠性,建議設定成 no 或 everysec。

除此之外,避免 AOF 檔案過大, Redis 會進行 AOF 重寫,產生縮小的 AOF 檔案。

可以把設定項 no-appendfsync-on-rewrite設定為 yes,表示 AOF 重寫時,不進行 fsync 作業。

也就是說,Redis 實例把寫指令寫到記憶體後,不呼叫後台執行緒進行 fsync 操作,就直接回傳了。

expires 淘汰過期資料

Redis 有兩種方式淘汰過期資料:

  • 惰性刪除:當接收請求的時候發現 key 已經過期,才執行刪除;

  • #定時刪除:每 100 毫秒刪除一些過期的 key。

不定時刪除的演算法如下:

隨機取樣 ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP個數的 key,刪除所有過期的 key;

如果發現有超過 25 % 的 key 已過期,則執行步驟一。

ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP預設為 20,每秒鐘執行 10 次,刪除 200 個 key 問題不大。

如果觸發了第二條,就會導致 Redis 一致在刪除過期資料去釋放記憶體。而刪除是阻塞的。

觸發條件是什麼呀?

也就是大量的 key 設定了相同的時間參數。同一秒內,大量 key 過期,需重複刪除多次才能降到 25% 以下。

簡而言之:大量同時到期的 key 可能會導致效能波動。

如果一批 key 的確實同時過期,可以在 EXPIREAT 和 EXPIRE 的過期時間參數上,加上一個一定大小範圍內的隨機數,這樣,既保證了 key 在一個鄰近時間範圍內被刪除,又避免了同時過期造成的壓力。

bigkey

通常我們會將含有較大資料或含有大量成員、清單數量的 Key 稱為大 Key,而下面我們將以幾個實際的範例來描述大 Key 的特性:

  • 一個 STRING 類型的 Key,它的數值為 5MB(資料過大)

  • #一個 LIST 類型的 Key,它的清單數量為 10000 個(清單數量太多)

  • ##一個 ZSET 類型的 Key,它的成員數量為 10000 個(成員數量過多)

  • 一個 HASH 格式的 Key,它的成員數量雖然只有 1000 個但這些成員的 value 總大小為 10MB(成員體積過大)

bigkey 帶來問題如下:

  • Redis 記憶體不斷變大引發 OOM,或達到 maxmemory 設 置值引發寫入阻塞或重要 Key 逐出;

  • Redis Cluster 中的某個 node 記憶體遠超過其餘 node,但因 Redis Cluster 的資料遷移最小粒徑為 Key 而無法將 node 上的記憶體均衡化;

#11

##bigkey 的讀取請求佔用過大頻寬,自身變慢的同時影響到該伺服器上的其它服務;

刪除一個 bigkey 造成主函式庫較長的時間阻塞並引發同步中斷或主從切換;

尋找 bigkey

使用 redis-rdb-tools 工具以客製化方式找出大 Key。

對大 key 分割

如將一個含有數萬成員的 HASH Key 分割為多個 HASH Key,並確保每個 Key 的成員數量在合理範圍,在 Redis Cluster 結構中,大 Key 的分割對 node 間的記憶體平衡能夠發揮顯著作用。

非同步清理大 keyRedis 自 4.0 起提供了 UNLINK 指令,該指令能夠以非阻塞的方式緩慢逐步的清理傳入的 Key,透過 UNLINK,你可以安全的刪除大 Key 甚至特大 Key。

###總結######如下檢查清單,幫助你在遇到 Redis 表現變慢的時候能有效率地解決問題。 ######取得目前 Redis 的基準效能;######開啟慢速指令監控,定位慢指令導致的問題;######找到慢指令,使用 scan 的方式;#### ##將執行個體的資料大小控制在 2-4GB,避免主從複製載入過大 RDB 檔案而阻塞;######停用記憶體大頁,採用了記憶體大頁,產生 RDB 期間,即使客戶端修改的數據只有 50B 的數據,Redis 需要複製 2MB 的大頁。當寫的指令比較多的時候就會導致大量的拷貝,導致效能變慢。 ######Redis 使用的記憶體是否過大導致 swap;#####AOF 設定是否合理,可將設定項 no-appendfsync-on-rewrite 設定為 yes,避免 AOF 重寫和 fsync 競爭磁碟IO 資源,導致 Redis 延遲增加。 ######bigkey 會帶來一系列問題,我們需要進行分割防止出現 bigkey,並透過 UNLINK 非同步刪除。 ######推薦學習:###Redis學習教學######

以上是Redis突然變慢?一起分析如何確定Redis有效能問題以及如何解決的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:苏三说技术公众号。如有侵權,請聯絡admin@php.cn刪除
REDIS:提高應用程序性能和可擴展性REDIS:提高應用程序性能和可擴展性Apr 17, 2025 am 12:16 AM

Redis通過緩存數據、實現分佈式鎖和數據持久化來提升應用性能和可擴展性。 1)緩存數據:使用Redis緩存頻繁訪問的數據,提高數據訪問速度。 2)分佈式鎖:利用Redis實現分佈式鎖,確保在分佈式環境中操作的安全性。 3)數據持久化:通過RDB和AOF機制保證數據安全性,防止數據丟失。

REDIS:探索其數據模型和結構REDIS:探索其數據模型和結構Apr 16, 2025 am 12:09 AM

Redis的數據模型和結構包括五種主要類型:1.字符串(String):用於存儲文本或二進制數據,支持原子操作。 2.列表(List):有序元素集合,適合隊列和堆棧。 3.集合(Set):無序唯一元素集合,支持集合運算。 4.有序集合(SortedSet):帶分數的唯一元素集合,適用於排行榜。 5.哈希表(Hash):鍵值對集合,適合存儲對象。

REDIS:對其數據庫方法進行分類REDIS:對其數據庫方法進行分類Apr 15, 2025 am 12:06 AM

Redis的數據庫方法包括內存數據庫和鍵值存儲。 1)Redis將數據存儲在內存中,讀寫速度快。 2)它使用鍵值對存儲數據,支持複雜數據結構,如列表、集合、哈希表和有序集合,適用於緩存和NoSQL數據庫。

為什麼要使用redis?利益和優勢為什麼要使用redis?利益和優勢Apr 14, 2025 am 12:07 AM

Redis是一個強大的數據庫解決方案,因為它提供了極速性能、豐富的數據結構、高可用性和擴展性、持久化能力以及廣泛的生態系統支持。 1)極速性能:Redis的數據存儲在內存中,讀寫速度極快,適合高並發和低延遲應用。 2)豐富的數據結構:支持多種數據類型,如列表、集合等,適用於多種場景。 3)高可用性和擴展性:支持主從復制和集群模式,實現高可用性和水平擴展。 4)持久化和數據安全:通過RDB和AOF兩種方式實現數據持久化,確保數據的完整性和可靠性。 5)廣泛的生態系統和社區支持:擁有龐大的生態系統和活躍社區,

了解NOSQL:Redis的關鍵特徵了解NOSQL:Redis的關鍵特徵Apr 13, 2025 am 12:17 AM

Redis的關鍵特性包括速度、靈活性和豐富的數據結構支持。 1)速度:Redis作為內存數據庫,讀寫操作幾乎瞬時,適用於緩存和會話管理。 2)靈活性:支持多種數據結構,如字符串、列表、集合等,適用於復雜數據處理。 3)數據結構支持:提供字符串、列表、集合、哈希表等,適合不同業務需求。

REDIS:確定其主要功能REDIS:確定其主要功能Apr 12, 2025 am 12:01 AM

Redis的核心功能是高性能的內存數據存儲和處理系統。 1)高速數據訪問:Redis將數據存儲在內存中,提供微秒級別的讀寫速度。 2)豐富的數據結構:支持字符串、列表、集合等,適應多種應用場景。 3)持久化:通過RDB和AOF方式將數據持久化到磁盤。 4)發布訂閱:可用於消息隊列或實時通信系統。

REDIS:流行數據結構指南REDIS:流行數據結構指南Apr 11, 2025 am 12:04 AM

Redis支持多種數據結構,具體包括:1.字符串(String),適合存儲單一值數據;2.列表(List),適用於隊列和棧;3.集合(Set),用於存儲不重複數據;4.有序集合(SortedSet),適用於排行榜和優先級隊列;5.哈希表(Hash),適合存儲對像或結構化數據。

redis計數器怎麼實現redis計數器怎麼實現Apr 10, 2025 pm 10:21 PM

Redis計數器是一種使用Redis鍵值對存儲來實現計數操作的機制,包含以下步驟:創建計數器鍵、增加計數、減少計數、重置計數和獲取計數。 Redis計數器的優勢包括速度快、高並發、持久性和簡單易用。它可用於用戶訪問計數、實時指標跟踪、遊戲分數和排名以及訂單處理計數等場景。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
1 個月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它們
1 個月前By尊渡假赌尊渡假赌尊渡假赌

熱工具

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

WebStorm Mac版

WebStorm Mac版

好用的JavaScript開發工具

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),