Redis 是什么?Redis 的数据类型和应用场景

摘要:Redis(Remote Dictionary Server,远程字典服务 ),是一个使用 ANSI C 语言编写的开源(遵守 BSD 协议)程序,包含多种数据结构,支持网络,可基于内存亦可持久化的日志型、Key-Value(键值对)数据库,是现在最受欢迎的 NoSQL 数据库之一。

引言

在 Web 应用发展的初期,那时关系型数据库受到了较为广泛的关注和应用,原因是因为那时候 Web 站点基本上访问和并发不高、交互也较少。

而在后来,随着访问量的提升,使用关系型数据库的 Web 站点多多少少都开始在性能上出现了一些瓶颈,而瓶颈的源头一般是在磁盘的 I/O 上。

而随着互联网技术的进一步发展,各种类型的应用层出不穷,这导致在当今云计算、大数据盛行的时代,对性能有了更多的需求,主要体现在以下四个方面:

  • 低延迟的读写速度:应用快速地反应能极大地提升用户的满意度。
  • 支撑海量的数据和流量:对于搜索这样大型应用而言,需要利用 PB 级别的数据和能应对百万级的流量。
  • 大规模集群的管理:系统管理员希望分布式应用能更简单的部署和管理。
  • 庞大运营成本的考量:IT 部门希望在硬件成本、软件成本和人力成本能够有大幅度地降低。

简介

Redis 是什么

Redis(Remote Dictionary Server,远程字典服务 ),是一个使用 ANSI C 语言编写的开源(遵守 BSD 协议)程序,包含多种数据结构,支持网络,可基于内存亦可持久化的日志型、Key-Value(键值对)数据库,是现在最受欢迎的 NoSQL 数据库之一。

Redis 的诞生

Redis 的创建者,叫 Salvatore Sanfilippo,网名 antirez,出生于意大利的西西里岛。

早年是系统管理员,2004-2006 年做嵌入式方面的工作,之后接触 WEB,2007 年和朋友共同创建了一个网站 LLOOGG.com,并为了解决这个网站的负载问题而在 2009 年发明了 Redis。

LLOOGG.com 网站是一个访客信息追踪网站,网站可以通过 javascript 脚本,将访客的 IP 地址、所属国家、阅览信息、访问页面地址等数据传送给 LLOOGG.com。

发送浏览记录

然后 LLOOGG.com 会将这些浏览数据通过 WEB 页面实时地展示给用户,并存储起来最新的 5 到 10000 条浏览记录以便进行查阅,就是说用户可以设置想看最近的多少条。

LLOOGG.com 用户界面

这个就是 LLOOGG.com 的用户界面,ps:Google 的 Analytics 直到 2011 年才有了实时功能,所以说 LLOOGG.com 的实时反馈想法在当时 2007 年还是很有新意的。

为了记录每个被追踪网站的浏览信息,LLOOGG.com 需要为每个被追踪的网站创建一个列表(list),每个列表需要根据用户的设置,储存最新的 5 到 10000 条浏览记录。

LLOOGG 的运作方式

每当某个被追踪的网站新增一条浏览记录时, LLOOGG.com 就会按照 FIFO 机制将这条新的浏览记录推入(push)到与该网站相对应的列表里面,当列表的长度超过用户指定的最大长度时,程序每向列表推入一条新的记录,就需要从列表中弹出(pop)一条最旧的记录。

FIFO 机制

随着 LLOOGG 的用户越来越多,LLOOGG 要维护的列表数量也越来越多,要执行的推入和弹出操作也越来越多。

当时 LLOOGG 使用 MYSQL 数据库,而每次 MYSQL 执行推入和弹出操作都要进行硬盘写入和读取,程序的性能严重受制于硬盘 I/O,很多操作都堆在那里,然后网站整个就没法运作了。

这个负载问题的根本原因就是这个硬盘 IO,所以 antirez 在不改变硬件的基础上,通过提升列表操作的性能来解决负载问题,决定自己写一个具有列表结构的内存数据库原型。

最重要的是数据存储在内存而不是硬盘,所以程序的性能不会受到硬盘 IO 限制,可以以极快的速度执行针对列表的堆入和弹出操作。

结果试验,确实解决了 LLOOGG 当时的负载问题,于是 antirez 使用 C 语言重写了这个内存数据库,并给它加上了持久化功能,这个就是 Redis 的诞生!

Redis 的演进

数据结构

Redis 核心对象

Redis 内部使用一个 redisObject 对象来表示所有的 key(键)和 value(值),其主要的结构如下:

  • type:数据类型,代表一个 value 对象具体是何种数据类型;
  • encoding:编码方式,是不同数据类型在 Redis 内部的存储方式,即数据结构;
  • ptr:数据指针,它指向具体的数据;
  • vm:虚拟内存,只有打开了 Redis 的虚拟内存功能,vm 字段才会真正的分配内存,该功能默认是关闭状态的。
  • redisObject 结构

    比如:

  • type=string 代表 value 存储的是一个普通字符串,那么对应的 encoding 可以是 raw(字符串)或 int(数值型);
  • 如果是 int,则代表是使用数值型(整数)存储和表示这个字符串的,比如 "123" "456" 这样的字符串。

下面,让我们先来简单了解下数据结构(即编码方式),再了解数据类型。

Redis 数据结构

Redis 一共有六种数据结构,分别是简单动态字符串、链表、压缩列表、字典、整数集合、跳表,它们和数据类型之间的关系如下图。

Redis 数据类型和数据结构

简单动态字符串(SDS)

基于 C 语言中传统字符串的缺陷,Redis 自己构建了一种名为 SDS(Simple Dynamic String,简单动态字符串)的抽象类型,其结构如下:

SDS 结构

SDS 几乎贯穿了 Redis 的所有数据结构,应用十分广泛。和 C 字符串相比,SDS 具有以下优点:

C 字符串和 SDS 特点

  • 常数复杂度获取字符串长度
  • 杜绝缓冲区溢出
  • 减少修改字符串时带来的内存重分配次数
  • 二进制安全
  • 兼容部分 C 字符串函数

链表(list)

链表(list)

  • 链表被广泛用于实现 Redis 的各种功能,比如列表键、发布与订阅、慢查询、监视器等;
  • 每个链表节点由一个 listNode 结构来表示,每个节点都有一个指向前置节点和后置节点的指针,所以 Redis 的链表实现是双向链表;
  • 每个链表使用一个 list 结构来表示,这个结构带有表头节点指针、表尾节点指针,以及链表长度等信息;
  • 因为链表表头节点的前置节点和表尾节点的后置节点都指向 NULL,所以 Redis 的链表实现是无环链表;
  • 通过为链表设置不同的类型特定函数,Redis 的链表可以用于保存各种不同类型的值。

字典(dict)

字典(dict)

  • 字典被广泛用于实现 Redis 的各种功能,其中包括数据库和哈希键;
  • Redis 中的字典使用哈希表作为底层实现,每个字典带有两个哈希表,一个平时使用,另一个仅在进行 rehash 时使用;
  • 当字典被用作数据库的底层实现,或者哈希键的底层实现时,Redis 使用 MurmurHash2 算法来计算键的哈希值;
  • 哈希表使用键地址法来解决键冲突,被分配到同一个索引上的多个键值对,会连接成一个单向链表;
  • 在对哈希表进行扩展或者收缩操作时,程序需要将现有哈希表包含的所有键值对,rehash 到新哈希表里面,并且这个 rehash 过程并不是一次性地完成的,而是渐进式地完成的。

压缩列表(ziplist)

压缩列表(ziplist)是列表键和哈希键的底层实现之一。当一个列表链只包含少量列表项,并且每个列表项要么就是小整数值,要么就是长度比较短的字符串,那么 Redis 就会使用压缩列表来做列表键的底层实现。

压缩列表(ziplist)

  • 压缩列表是一种为节约内存而开发的顺序型数据结构;
  • 压缩列表被用作列表键和哈希键的底层实现之一;
  • 压缩列表可以包含多个节点,每个节点可以保存一个字节数组或者整数值;
  • 添加新节点到压缩列表,或者从压缩列表中删除节点,可能会引发连锁更新操作,但这种操作出现的几率并不高。

整数集合(intset)

整数集合(intset)是集合键的底层实现之一,当一个集合只包含整数值元素,并且这个集合的元素数量不多时,Redis 就会使用整数集合作为集合键的底层实现。

整数集合(intset)

  • 整数集合是集合键的底层实现之一;
  • 整数集合的底层实现为数组,这个数组以有序、无重复的方式保存集合元素,在有需要时,程序会根据新添加元素的类型,改变这个数组的类型;
  • 升级操作为整数集合带来了操作上的灵活性,并且尽可能地节约了内存;
  • 整数集合只支持升级操作,不支持降级操作。

跳表(skiplist)

跳表(skiplist)是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。跳表查询的时间复杂度 O(logN)、最坏情况是 O(N),还可以通过顺序操作来指处理节点。

跳表(skiplist)

  • 跳表是有序集合的底层实现之一;
  • Redis 的跳表实现由 zskiplist 和 zskiplistNode 两个结构组成,其中 zskiplist 用于保存跳表信息(比如表头节点、表尾节点、长度),而 zskiplistNode 则用于表示跳表节点;
  • 每个跳表节点的层高都是 1 至 32 之间的随机数;
  • 在同一个跳表中,多个节点可以包含相同的分值,但每个节点的成员对象必须是唯一的;
  • 跳表中的节点按照分值大小进行排序,当分值相同时,节点按照成员对象的大小进行排序。

数据类型

Redis 数据类型

Redis 所有的数据结构都是以唯一的 key 字符串作为名称,然后通过这个唯一 key 值来获取相应的 value 数据,不同类型的数据结构的差异就在于 value 的结构不一样。

Redis 数据类型

Redis 支持五种数据类型:string(字符串)、hash(哈希)、list(列表)、set(集合)、zset(sorted set:有序集合)

  • 字符串(string)
  • 字符串列表(list)
  • 无序不重复的字符串集合(set)
  • 有序不重复的字符串集合(zset)
  • 键、值都为字符串的哈希表(hash)

String(字符串)

String 是最基本的数据类型,对应到数据结构里,就是 Redis 里的简单动态字符串(SDS)。它是一个二进制安全的字符串,最大长度为 512 M。

Redis 字符串

字符串结构使用非常广泛,一个常见的用途就是缓存用户信息。

我们将用户信息结构体使用 JSON 序列化成字符串,然后将序列化后的字符串塞进 Redis 来缓存。同样,取用户信息会经过一次反序列化的过程。

序列化(Serialization)是指将对象的状态信息转换为可以存储或传输的形式的过程。

  • 在序列化期间,对象将其当前状态写入到临时或持久性存储区;
  • 以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。

Redis 的字符串是动态字符串,是可以修改的字符串,内部结构实现上类似于 Java 的 ArrayList,采用预分配冗余空间的方式来减少内存的频繁分配。

如图所示,Redis 内部为当前字符串实际分配的空间 capacity(容量),一般要高于实际字符串长度 len。

字符串长度

当字符串长度小于 1M 时,扩容都是加倍现有的空间,如果超过 1M,扩容时一次只会多扩 1M 的空间。

它是一个二进制安全的字符串,意味着它不仅能够存储字符串,还能存储经过序列化的对象(如图片、视频等多种类型)。

  • 常用命令:SET、SETEX、MSET、MSETNX、GET、MGET、GETSET、INCR、DECR、DEL 等;
  • 应用场景:String 是最常用的一种数据类型,普通的 key/value 存储都可以归为此类;
  • 实现方式:String 在 Redis 内部存储默认就是一个字符串,被 redisObject 所引用,当遇到 incr、decr 等操作时会转成数值型进行计算,此时 redisObject 的 encoding 字段为 int。

Hash(哈希)

Hash 是一个键值对集合,由 field(字段)和 value(值)组成的 Map(映射表,将键映射到值的对象,一个映射不能包含重复的键,每个键最多只能映射到一个值)。其中,field 和 value 都是字符串类型。

Hash

Hash 结构也可以用来存储用户信息,每个 Hash 可以存储 232-1=4294967295 键值对(40 多亿),有两种实现方式,压缩列表和字典。

只有当存储的数据量比较小的情况下,Hash 才使用压缩列表来实现。具体需要满足两个条件:

  • Hash 中保存的键和值的大小都要小于 64 字节;
  • Hash 中键值对的个数要小于 512 个。

不同于字符串一次性需要全部序列化整个对象,Hash 可以对用户结构中的每个字段单独存储,这样当我们需要获取用户信息时可以进行部分获取。

而以整个字符串的形式,去保存用户信息的话,就只能一次性全部读取,这样就会比较浪费网络流量。

Redis 的 Hash 相当于 Java 语言里面的 HashMap,它是无序字典,内部实现结构上同 Java 的 HashMap 也是一致的。

实际上是内部存储的 Value,该 Value 由 field(属性名)和 value(属性值)组成,一个或多个 Value 的集合称为 HashMap(哈希表),并提供了存取这个 Map 成员的接口。

HashMap

如图所示,Key 是用户 ID,Value 是一个 HashMap。这个 Map 的 key 是成员的属性名(field),value 是属性值。

这样对数据的修改和存取,都可以直接通过 key(用户 ID)+ field(属性标签)就可以操作对应的属性数据(value)。

  • 常用命令:HGET、HMGET、HGETALL、HSET、HMSET、HSETNX、HEXISTS、HLEN、HKEYS、HDEL、HVALS 等;
  • 应用场景:我们要存储一个用户信息,其中包括用户 ID、姓名、年龄和生日等,通过用户 ID 我们希望获取该用户的姓名、或年龄、或生日等;

  • 实现方式:当 HashMap 的成员比较少时,Redis 为了节省内存会采用类似一维数组的方式来紧凑存储,即压缩列表;当成员数量增大时,会自动转成真正的 HashMap 结构,此时 encoding(编码方式)为 ht(字典)。

List(列表)

List 是简单的字符串列表,基于双链表实现,按照插入顺序排序,每个列表最多可存储 232-1=4294967295 元素(40 多亿)。

Redis 列表

同样,当列表中存储的数据量比较小的时候,列表就可以采用压缩列表的方式实现。具体需要同时满足下面两个条件:

  • 列表中保存的单个数据(有可能是字符串类型的)小于 64 字节;
  • 列表中数据个数少于 512。

Redis 的列表相当于 Java 语言里面的 LinkedList,注意它是链表而不是数组,这意味着 List 的插入和删除操作非常快。

常用来做异步队列使用,将需要延后处理的任务结构体序列化成字符串塞进 Redis 的列表,另一个线程从这个列表中轮询数据进行处理。

Redis 列表

  • 常用命令:LPUSH、LPUSHX、LPOP、RPUSH、RPUSHX、RPOP、LINSERT、LSET、LINDEX、LRANGE、LLEN、LTRIM 等;
  • 应用场景:List 的应用场景很多,如 Twitter 的关注列表,粉丝列表等都可以用 Redis 的 List 结构来实现;
  • 实现方式:List 的实现为一个双向链表,支持反向查找和遍历,方便操作,不过会带来部分额外的内存开销,Redis 内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构。

Set(集合)

Set 是字符串类型元素的无序集合,基于哈希表(字典)实现,集合中最大的成员数为 232-1=4294967295(40 多亿)。

Redis 集合

  • 集合成员是唯一的,所以集合中不能出现重复的数据;
  • 集合是通过哈希表(字典)实现的,所以添加、删除、查找的时间复杂度都是 O(1);
  • 集合成员不超过 512 个,且数据都是整数,Redis 就采用整数集合来实现。

Redis 的集合相当于 Java 语言里面的 HashSet,它内部的键值对是无序的唯一的。

用户可以快速地向集合添加元素,或者从集合里面删除元素,也可以对多个集合进行集合运算操作,比如计算并集、交集和差集。

并集、交集和差集

  • 并集(union):设 A、B 是两个集合,把它们所有的元素合并在一起组成的集合,叫做 A 与 B 的并集,记作 A∪B。
  • 交集(intersection):设 A、B 是两个集合,所有属于 A 且属于 B 的元素所组成的集合,叫做 A 与 B 的交集,记作 A∩B。
  • 差集(except):设 A、B 是两个集合,所有属于 A 但不属于 B 的元素组成的集合,叫 A 与 B 的相对差集,记作 A\B 或 A-B。
  • 补集(complement):设 A、B 是两个集合且 B 是 A 的子集,所有属于 A 但不属于 B 的元素组成的集合,叫做子集 B 在全集 A 中的绝对补集。
  • 常用命令:SADD、SPOP、SMOVE、SCARD、SINTER、SDIFF、SDIFFSTORE、SUNION;
  • 应用场景:使用集合可以实现如微博的共同关注、淘宝的商品筛选、网站统计等;
  • 实现方式:Set 的内部实现是一个 value 永远为 null 的 HashMap,实际就是通过计算 hash 的方式来快速排重的,这是 Set 能提供判断一个成员是否在集合内的原因。

zset(sorted set:有序集合)

zset 是字符串类型元素的有序集合,基于哈希表实现,每个元素都会关联一个浮点数格式的分数(score),通过分数来为集合中的成员进行从小到大的排序。

Redis 有序集合

  • 有序集合的成员是唯一的,但分数(score)可以重复,最大的成员数为 232-1=4294967295(40 多亿);
  • 有序集合也有两种实现方式,跳跃表和压缩列表;
  • 有序集合的成员不超过 128 个,且所有数据的大小都要小于 64 字节,Redis 就采用压缩列表来实现。

有序集合使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。比如可以用来存储粉丝列表,value 值是粉丝的用户 ID,score 是关注时间,我们可以对粉丝列表按关注时间进行排序。

  • 常用命令:ZADD、ZPOP、ZMOVE、ZCARD、ZCOUNT、ZINTER、ZDIFF、ZDIFFSTORE、ZUNION;
  • 应用场景:排行榜、带权重的消息队列等,比如 Twitter 的 public timeline 可以以发表时间作为 score 来存储,这样获取时就是自动按时间排好序的;

  • 实现方式:zset 的内部使用 HashMap 和跳跃表(skiplist)来保证数据的存储和有序,HashMap 里放的是成员到 score 的映射,而跳跃表里存放的是所有的成员,排序依据是 HashMap 里存的 score。

更多 Redis 命令参考:http://doc.Redisfans.com/

总结

最后,我们来总结下各种数据类型的特性及应用场景。

Redis 数据结构和特性

类型 简介 特性 场景
String(字符串) 二进制安全 可以包含任何数据,比如 jpg 图片或者序列化的对象,一个键最大能存储 512 M。
Hash(哈希) 键值对集合,即编程语言中的 Map 类型。 适合存储对象,并且可以像数据库中 update 一个属性一样,只修改某一项属性值。
(Memcached 中需要取出整个字符串,反序列化成对象,修改完再序列化存回去。)
存储、读取、修改用户属性。
List(列表) 链表(双向链表) 增删快,提供了操作某一段元素的 API。 1,最新消息排行等功能(如朋友圈的时间线);2,消息队列。
Set(集合) 哈希表实现,元素不重复。 1,添加、删除、查找的时间复杂度都是 O(1);
2,为集合提供了求交集、并集、差集等操作。
1,共同好友;
2,利用唯一性,统计访问网站的所有独立 IP;
3,好友推荐时,根据 tag 求交集,大于某个阈值就可以推荐。
Sorted Set(有序集合) 将 Set 中的元素增加一个权重参数 score(分数),元素按 score 有序排列。 数据插入集合时,已经进行天然排序。 1,排行榜;2,带权重的消息队列。

应用场景

下面来一一分析下 Redis 的应用场景都有哪些。

Redis 的应用场景

缓存

缓存现在几乎是所有中大型网站都在用的必杀技,合理的利用缓存不仅能够提升网站访问速度,还能大大降低数据库的压力。Redis 提供了键过期功能,也提供了灵活的键淘汰策略,所以,现在 Redis 用在缓存的场合非常多。

例如:缓存 "热点" 数据(高频读、低频写),对象缓存、全页缓存等,可以提升热点数据的访问数据。

计数器

什么是计数器,如电商网站商品的浏览量、视频网站视频的播放数等。为了保证数据实时效,每次浏览都得给 +1,并发量高时如果每次都请求数据库操作无疑是种挑战和压力。

Redis 提供的 incr 命令来实现计数器功能,内存操作,性能非常好,非常适用于这些计数场景。

社交网络

点赞、踩、关注/被关注、共同好友等是社交网站的基本功能,社交网站的访问量通常来说比较大,而且传统的关系数据库类型不适合存储这种类型的数据,Redis 提供的哈希、集合等数据结构能很方便的的实现这些功能。

位图

在我们平时开发过程中,会有一些 bool 型数据需要存取,比如用户一年的签到记录,签了是 1,没签是 0,要记录 365 天。

如果使用普通的 key/value,每个用户要记录 365 个,当用户上亿的时候,需要的存储空间是惊人的。

为了解决这个问题,Redis 提供了位图数据结构,这样每天的签到记录只占据一个位,365 天就是 365 个位,46 个字节 (一个稍长一点的字符串) 就可以完全容纳下,这就大大节约了存储空间。

排行榜

很多网站都有排行榜应用的,如京东的月度销量榜单、网易云音乐排行榜等。Redis 提供的有序集合数据类构,能实现各种复杂的排行榜应用。

网易云音乐排行榜

分布式锁

在很多互联网公司中都使用了分布式技术,分布式技术带来的技术挑战是对同一个资源的并发访问,如全局 ID、减库存、秒杀等场景,并发量不大的场景可以使用数据库的悲观锁、乐观锁来实现。

但在并发量高的场合中,利用数据库锁来控制资源的并发访问是不太理想的,大大影响了数据库的性能。

可以利用 Redis 的 setnx 功能来编写分布式的锁,如果设置返回 1 说明获取锁成功,否则获取锁失败,实际应用中要考虑的细节要更多。

分布式会话

集群模式下,在应用不多的情况下,一般使用容器自带的 Session 复制功能就能满足。

当应用增多相对复杂的系统中,一般都会搭建以 Redis 等内存数据库为中心的 Session 服务,Session 不再由容器管理,而是由 Session 服务及内存数据库管理。

最新列表

Redis 列表结构,LPUSH 可以在列表头部插入一个内容 ID 作为关键字,LTRIM 可用来限制列表的数量,这样列表永远为 N 个 ID,无需查询最新的列表,直接根据 ID 去到对应的内容页即可。

消息队列

消息队列是大型网站必用中间件,如 ActiveMQ、RabbitMQ、Kafka 等流行的消息队列中间件,主要用于业务解耦、流量削峰及异步处理实时性低的业务。

Redis 提供了发布/订阅及阻塞队列功能,能实现一个简单的消息队列系统。另外,这个不能和专业的消息中间件相比。

消息队列

HyperLogLog

geoHash 附近的人

总结

  • Redis 基于内存运行,性能高效,读的速度是 110000 次/s,写的速度是 81000 次/s;
  • Redis 支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用;
  • Redis 的所有操作都是原子性,即在执行过程中不会被任何其它任务或事件中断;
  • Redis 不仅仅支持简单的 key-value 类型的数据,同时还提供 list,set,zset,hash 等数据结构的存储;
  • Redis 支持 master-slave(主从复制)模式数据的备份,即主机数据更新后根据配置和策略,自动同步到备机;
  • Redis 还支持 pub/sub(发布/订阅)、通知、key(键)过期等特性。

Redis 相关资源

Redis 官网:https://Redis.io/

源码地址:https://github.com/Redis/Redis

Redis 在线测试:http://try.Redis.io/

Redis 命令参考:http://doc.Redisfans.com/

antirez Twitter:https://twitter.com/antirez

版权声明:本文为博主原创文章,未经博主允许不得转载。http://www.dedenotes.com/html/redis.html
(1)
打赏 微信扫一扫 微信 支付宝 QQ 扫码打赏

防止表单重复提交的 4 种方法

Dedenotes 赞(3)

平时开发的项目中可能会出现下面这些情况:由于用户误操作,多次点击表单提交按钮;由于网速等原因造成页面卡顿,用户重复刷新提交页面;黑客或恶意用户使用 Postman 等工具重复恶意提交表单(攻击网站)。

meta

Dedenotes 赞(3)

meta 是 html 语言 head 区的一个辅助性标签,位于文档的头部,不包含任何内容,标签的属性定义了与文档相关联的名称/值对。meta 标签可提供相关页面的元信息(meta-information),比如针对搜索引擎和更新频度的描述和关键词。

HTTP消息结构 HTTP请求报文和响应报文的格式

Dedenotes 赞(3)

HTTP 协议(HyperText Transfer Protocol,超文本传输协议)是因特网上应用最为广泛的一种网络传输协议,基于 TCP/IP 通信协议来传递数据(HTML 文件, 图片文件, 查询结果等),所有的 WWW(World Wide Web)文件都必须遵守这个标准。