Redis Sentinel 文档说明_第1页
Redis Sentinel 文档说明_第2页
Redis Sentinel 文档说明_第3页
Redis Sentinel 文档说明_第4页
Redis Sentinel 文档说明_第5页
已阅读5页,还剩13页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Redis Sentinel 文档说明 Redis Sentinel 的设计目标是用来协助管理Redis实例的系统,它通常执行下面的4类任务:  · 监控,Sentinel会持续的检测master和slave的实例是否像期望的方式工作。 · 通知,Sentinel可以通过一个API,通知系统管理员,或计算机上的其他程序,它监控的redis实例中那些事情出错了。· 自动的错误恢复,如果一个master不能像期望的那样正常工作,Sentinel可以启动一个错误恢复的处理过程, 将一个slave升级成为master,并使其他的sl

2、ave成为新的master的slave,应用使用Redis server获取新master位置的通知。 · 配置信息的获取,Sentinel会作为面向客户端的服务的一个发现的源头:客户端会通过与Sentinels连接,来获取当前工作的Redis master 的位置。如果经历了错误恢复,Sentinels将会报告新的master的地址。 Sentinel的分布式本质(Distributed nature of Sentinel) Redis Sentinel是一个可分布的系统,这意味着通常你会在你的基础规划中选择运行多个Sentinel进程,而这些进程会

3、使用gossip protocols来理解一个master是否下线,并使用agreement protocols来获取执行错误恢复的授权,或赋予一个新配置新的版本。 分布式系统具有安全(safety)和活动(liveness)的特性,如果想能使用好Redis Sentinel,你应该理解Sentinel是如果作为一个分布式系统工作的。这些使Sentinel与单进程的程序相比,会更复杂并更具有优势,如:· 一个Sentinels的群集,即便其中一部分Sentinels失效,仍然可以完成一个master的故障恢复。· 如果一个Sentinel工作不正常,或连接不上,不

4、会得到其它的Sentinels的授权,也就不可能做故障恢复的工作。· 客户端可以连接任意的Sentinel来获取master的配置信息。  获取Sentinel(Obtaining Sentinel) Sentinel当前是Redis source code的Github上的一个unstable的分支,不过自Redis 2.8开始,会作为不定进入到Redis的发行版本。 使用Sentinel最简单的方式是下载Redis 2.8之后的最新版本,或编译Github上的最新的unstable的分支。 注意:即便你是在使用Redis 2.6,

5、你也应该使用Redis 2.8中的Sentinel。 运行Sentinel(Running Sentinel) 如果你使用的 redis-sentinel 可执行程序(或者是一个到 redis-server 可执行程序的符号链接), 你可以使用下面的命令运行Sentinel:redis-sentinel /path/to/sentinel.conf另外,你可以直接使用 redis-server 可执行程序使用 Sentinel 模式来启动:redis-server /path/to/sentinel.conf -sentinel这两种方式没什么区别。 此外,运行

6、Sentinel 被强制要求使用配置文件,因为这个文件会被 Sentinel 用来保存它的当前状态,以便可以在 Sentinel 重新启动的情况下可以恢复 Sentinel 的状态。如果没有配置文件,或配置文件不能写入,Sentinel 会拒绝启动。 Sentinel默认监听在26379的TCP端口,所以你的服务器必须开放 26379 端口,这样 Sentinel 才能接收来自其他IP的 Sentinel 的实例的连接。否则 Sentinels 将无法会话,也无法赞同应该做的事情,当然也无法执行错误恢复。 Sentinel的配置(Configuring Sentinel)&

7、#160;在 Redis 的发布的源代码中,包含一个 sentinel.conf 的文件,是一个自描述的Sentinel的配置文件的例子。一般,一个典型的最小化的配置看起来应该是下面这样子:sentinel monitor mymaster 127.0.0.1 6379 2sentinel down-after-milliseconds mymaster 60000sentinel failover-timeout mymaster 180000sentinel parallel-syncs mymaster 1sentinel monitor resque 192.168.1.3

8、6380 4sentinel down-after-milliseconds resque 10000sentinel failover-timeout resque 180000sentinel parallel-syncs resque 5第一行用于告知监控的 Redis 的 master ,被命名为mymaster, 位于 IP 127.0.0.1,端口 6379, 并且启动故障恢复的sentinels的同意的数量(agreement)是2(如果同意的数量没有达到,不会启动故障恢复的过程)。 然而,无论 Sentinel 需要达成什么一致,Sentinel 都要求所有

9、群集中的知道的Sentinels的主体的投票,来开始一个故障恢复和获取一个新生代的配置用来描述故障恢复后的配置状态。 在这个例子中,法定人数(quorum)被设置为2,因此需要两个sentinels赞同 master 已经无法联络,或处于一种可以触发故障恢复的错误状态(然而像下一个小节将看到的,触发故障恢复仅仅启动还是不够的,还需要授权)。 其他的配置项基本是下面的形式:sentinel <option_name> <master_name> <option_value>他们被用于下面的场景:· down-after-milli

10、seconds 是以毫秒计时的时间长度,当一个redis的实例不能联系上(或者是没有应答 PINGs 命令,或者是它返回了一个错误)的时候,Sentinel 开始认为它已经down了。如果这持续了这个指定的时间,当前的 Sentinel 会标记这个redis的实例为 SDOWN (subjectively down),这还不足以启动一个自动的故障恢复。然而,如果足够的 Sentinel 实例认为这个redis实例为 SDOWN,这个redis实例会被标记为 ODOWN(objectively down)。需要赞同的Sentinel 实例数量依赖于这个master的配置的同意的数量(a

11、greement)的配置。· parallel-syncs 设置经过故障恢复之后,可以同时被配置为新master的slaves的数量。这个数量配置的越小,执行故障恢复所需的时间就越长,然而如果slaves还用于提供数据服务,你可能不希望所有的slaves在同一时间都在和master同步。这样,当复制处理的过程中,一个slave大多会处于非阻塞的状态。你可以通过设置这个值为1,来确保一个时间之内,只有一个slave在同步。 其他的选项在 Redis 的发布的源代码中的 sentinel.conf 文件中描述。 所有的配置参数可以在运行期通过 SENTINE

12、L SET 命令来修改。看 在运行期配置Sentinel(Reconfiguring Sentinel at runtime)小节获取更多信息。 法定人数(Quorum) 前面的小节说明:每个被关联的 Sentinel 监控的 master,会涉及到一个配置的法定人数(quorum)。它指定了判断一个maser无法联系或处于需要触发故障恢复的错误状态的 所需的赞同的 Sentinel 的数量。 然而,如果故障恢复的条件达到,如果确实需要执行故障恢复,至少还需要 Sentinels 的主体的授权。 让我们把事情弄更清楚一些: · 法定人

13、数(quorum): 是检测到一个master并标记为 SDOWN 的 Sentinel 实例的数量,目标是将一个master标记为ODOWN。 · 故障恢复由 ODOWN 状态触发。· 一旦故障恢复被触发,这个试图执行故障恢复的 Sentinel 实例被强制获取Sentinels主体的授权(如果 quorum 被这种成大于主体的数字,会被要求多于主体的授权) 译者注:主体理解成大多数吧,也就是多于一半就好。 这种差别也许看起来很微妙,但是使用和理解上却是很简单。例如,如果你有5个Sentinel实例,并设置 quorum 为2,那么故障恢复在

14、 2 个 Sentinels 认为 master down的时候就会启动,然而需要至少 3 个Sentinels授权才会真正的开始故障恢复。 如果把 quorum 配置成 5,那么就需要所有的 Sentinels 认同 master down的时候,故障恢复才会启动,并且需要所有的 Sentinels 授权,故障恢复才会执行。 配置的代(Configuration epochs) Sentinels要求获取主体的授权来启动故障恢复是因为一些重要的原因:当一个 Sentinel 做出了授权,他就会获取到这个master故障恢复的唯一的配置的代(configurati

15、on epoch)。这是一个在故障恢复之后用来标记新配置的版本的数字。因为主体同意分配版本给一个 Sentinel,没有其他的 Sentinel 可以使用它。这意味着每一个故障恢复的每次配置都会有一个唯一的版本号。我们将会看到为什么这个如此重要。 此外 Sentinels 有一个规则:如果如果一个 Sentinel 给另外一个 Sentinel 的master的故障恢复投票,它会等待这个master的故障恢复一段的时间。这个时间就是在 sentinel.conf 中配置的 failover-timeout。这表示在这个期间 Sentinels 不会再对相同的master再做

16、故障恢复,然后尝试第一次的授权请求,如果失败再试,等等。 Redis Sentinel的 存活 的保证,来自Sentinels的主体的可交互性,最终体现在master的故障恢复的授权上。Redis Sentinel的 安全 的保证,来自每个 Sentinel 做同一个master的故障恢复,会使用一个不同的、唯一的配置的代。 配置的传播(Configuration propagation) 一旦一个 Sentinel  可以成功的对一个master做故障恢复,它会开始对广播这个新的配置,这样其它的  Sentinels 会根据广播的配

17、置更新自己的信息。 因为故障恢复被认为是成功的,它要求 Sentinel 可以发送 SLAVEOF NO ONE 命令给选择的 slave,并将其切换成为master。这可以通过在 master 上看 INFO 的命令的输出就能看到。 在设个时间点,即使slaves的配置还在继续,但这个故障恢复的过程已经被看作是成功的,并且所有的 Sentinels 要求报告新的配置。 新的配置的传播方式是为什么每个 Sentinel 被授权为一个不同版本号的原因(配置代)。 每个 Sentinel 会不断的广播它的 master 的配置的版本,使用Redis的Pub/

18、Sub命令,在所有的master和master的所有的slaves上。同时,所有的 Sentinels 也在等待其他的 Sentinels 广播的消息,来查看其他 Sentinels 广播的配置信息。 配置信息通过 _sentinel_:hello Pub/Sub channel来广播。 因为每个配置都有一个不同的版本号,因此更大的版本号总是会覆盖小的版本。 因此,例如,开始的时候所有的 Sentinels 认为 mymaster 的配置中,master位于 192.168.1.50:6379。这个配置具有版本 1。过了一些时间,一个 Sentinel

19、获得了授权执行了故障恢复,切换到版本 2。如果故障恢复成功,它开始广播新配置,假设是 192.168.50:9000,带有版本 2。所有其他 Sentinel 会看到这个配置,并将其更新到他们的配置之中,因为新的配置有更大的版本。 这意味着 Sentinel 提供了另外一个存活性的特性:一个 Sentinels 的集合可以相互通讯,并聚集到有更高版本、相同的配置下。 基本上,如果网络是分离的,每个部分都会聚集到更高的本地配置的版本下;在消除分区的特定情况下,所有Sentinel会成为一个分区,并会统一配置。 关于SDOWN 和ODOWN的更多的细节(Mo

20、re details about SDOWN and ODOWN) 像已经描述过的,Redis Sentinel 有两个不同的描述 down 的概念,一个是称为主观down(Subjectively Downcondition,SDOWN),是 Sentinel 实例在本地对down状态的判断。另外一个被称为客观 down (Objectively Downcondition,ODOWN),是收集了足够 Sentinels 实例(至少是 monitored master中 quorum 参数的数量 ) 提供了 SDOWN 的指示,并且从这些 Sentinels 使

21、用 SENTINEL is-master-down-by-addr 命令取得反馈。 简单的看, Sentinel 给出 SDOWN 的状态的条件,就是它在一个 is-master-down-after-milliseconds 配置参数指定的时间内没有收到 有效的 PING 请求的回复。 可以接受的 PING 的回复是下面这些:· PING replied with +PONG.· PING replied with -LOADING error. ·  PING replied with -M

22、ASTERDOWN error. 任何其他的回复(或没回复)认为是无效的。 注意,SDOWN 的条件是在整个配置的间隔时间内没有有效的回复,比如,如果间隔时间是30000 milliseconds (30 seconds),而我们的 PING 每次都在 29 后收到回复,这个redis 实例就被看作是有效的。 从 SDOWN 到 ODOWN 的切换是没有强制的一致性算法的,仅是 gossip 的一个实现:如果一个指定的 Sentinel 在一个给定的时间范围内,获得足够数量的Sentinels的报告,声称 master 已经失效,就会将 master 的状态从 S

23、DOWN 切换到 ODOWN。如果这个认可后来消失了,状态标志会被清除。 像已经阐述的,后面会执行一个更严格的授权机制来正式启动故障恢复机制,但如果没达到 ODOWN 状态,不会启动任何故障恢复的过程。 ODOWN 仅仅作用于 master。对于其它类型的 redis 实例,Sentinel 不会要求任何许可,因此对于 slaves 或其他的 sentinels 实例是不会出现 ODOWN 的状态的。 Sentinels和Sentinels的自动发现(Sentinels and Slaves auto discovery) 当 Sentinels 于其它

24、的 Sentinels 相互连接以相互检查彼此的可用性,并交换消息时,你不需要在 Sentinel 上配置其他 Sentinel 的地址,因为 Sentinel 使用 Redis 的 master 的 Pub/Sub 来发现其它的监控相同 master 的 Sentinel 的位置。 这是从名字为 _sentinel_:hello 的消息通道的 hello 消息中获取的信息。 类似的,你也不需要配置master有那些 slaves ,因为 Sentinel 会查询 redis 的信息来自动发现。· 每个 Sentinel  对每个监控的 master 和

25、 slave 每 2秒 发布一个消息,传递到其  _sentinel_:hello 消息通道,通告当前 Sentinel 的IP、端口和 runid。· 每个 Sentinel 都订阅每个监控的 master 和 slave 的    _sentinel_:hello 消息通道,查找未知的 sentinels。如果找到新的 sentinels,它们被添加作为 master 的 sentinels 中的一员。· Hello 消息也被包含到 master 的完整的配置之中。如果一个 Sentinel 拥有的配

26、置比它接收的任何一个配置要旧,它会马上升级到这个更新的配置。·  在添加一个新的 Sentinel 到 master 之前,Sentinel会检查 runid 或 地址(IP+端口)是否重复。所有重复的 Sentinel 会被删除,然后再添加新的 Sentinel。 分区后的一致性(Consistency under partitions) Redis Sentinel的配置是最终一致的,所以每个分区都会向可用的更高配置聚集。 而在真实的世界中 Sentinel 有 3个 不同的角色: · Redis instan

27、ces.· Sentinel instances.· Clients. 为了可以定义系统的行为,我们需要考虑这全部的 3个角色。 下面是一个简单的网络拓扑,有3个节点,每个节点上有一个 Redis 实例,一个 Sentinel 实例: +-+ | Sentinel 1 | <- Client A | Redis 1 (M) | +-+ | |+-+ | +-+| Sentinel 2 |-+- / partition / -| Sentinel 3 | <- Client B| Redis 2 (S) | | Redis 3 (M)|+-+

28、+-+在这个体系中原本 Redis 3 是 master,Redis 1 和 2 是 slaves。一个网络分区出现,隔离了原来的 master。然后 Sentinels 1 和 2启动了错误恢复的过程,将 Redis 1 升级为新的 master。 Sentinel 的特性保证 Sentinel 1 和 2 拥有 master 的新配置。但是 Sentinel 3 还停留在旧的配置,因为它在不同的网络分区。 我们知道 Sentinel 3 在网络分区消失的时候会获取最新的配置,但是在网络出现分区的时候如果有 clients 跟着老的

29、 master 出现分区会发生什么故事? Clients 会一直可以读、写 Redis 3,这个前 master。当分区合并时,Redis 3会被变成 Redis 1 的一个 slave,在分区出现期间所写入的数据都会丢失。 依赖于你的配置你也许可以或不能接受这个场景:· 如果将 Redis 作为 cache,Client B 在出现分区之后还能写数据到前 master 就很方便,即便这个数据会丢失。· 如果将 Redis 作为存储,这样就不好了,你需要配置系统来部分的预防这个问题。 因为 Redis 是异步复制的,在上面这个场景中没有完整的预

30、防数据丢失的方法,但是你可以使用 Redis 的配置项来处理 Redis 3 和 Redis 1 之间的差异:min-slaves-to-write 1min-slaves-max-lag 10使用上面的配置(请参考 Redis 发现版本中的 redis.conf 例子自描述配置文件)一个 Redis 实例,当 Redis 成为一个 master,如果有一个 slave 不能写入,那么这个 master 将会停止接收(clients)写入请求。因为复制是异步,(clients)不能写入意味着: slave 要么无法连接,或不会向我们发送超过 max-lag 秒之后的异步通告

31、。 上面的例子中,使用这个配置到  Redis 3,它会在 10秒后变成不可用。当分区融合之后,Sentinel 3 会聚集到新的配置,Client B 就可以获得一个有效的配置可以继续工作。 Sentinel状态的持久化(Sentinel persistent state) Sentineld 的状态被持久化到 sentinel 的配置文件。例如:对于一个 master 每次收到一个新的配置,或创建(leader Sentinels),配置都会将其和配置的代一同持久化配置文件中。这意味着停止和启动或重启 Sentinel 是很安全的。 

32、60;故障恢复之外对 Sentinel的重新配置(Sentinel reconfiguration of instances outside the failover procedure) 即使没有故障恢复,Sentinels 也会尝试对监控的 Redis 实例设置当前的配置。特别是:· Slaves (根据当前的配置)中声称是master的,会被配置成为当前 master 的一个slaves。 · Slaves 连接到错误的 master,会被配置连接正确的master。 因为 Sentinels 会配置 slaves,这些错误的配

33、置必须被观察一段时间,这比用于广播新配置的时间周期要大。 这是为了避免干扰 Sentinels 的配置稳定期间(如因网络分区导致的分区融合)对 slaves 的配置。 还有,注意,总是尝试聚集到当前的配置的语义,使故障恢复过程更可以对抗分区:· Masters 故障恢复后如果变的可用,会被重配置为slaves。· Slaves 如果被分区隔离,会在重新聚合之后被重新配置。 Sentinel API 默认情况下 Sentinel 运行在 26379 的TCP端口下(6379是一个 Redis 实例的普通端口)。Sentinels 使用

34、Redis 的协议来接收命令,因此你可以使用 redis-cli 或其他 Redis 客户端与 Sentinel 会话。 有两种和 Sentinel 会话的方式:可以直接从其查询监控的 Redis 进程的状态,看有那些其他的 Sentinels,等等。另外一个方式是使用 Pub/Sub 接收 Sentinels 推送的通知,每当有事情发生,如故障恢复,或一个实例出现错误,等等。 Sentinel的命令(Sentinel commands) 下面是可以接收的命令的列表:· PING 这个命令简单的返回 PONG。· SENTINEL master

35、s 显示有那些监控的 masters,以及他们的状态。· SENTINEL master <master name> 显示指定的 master 的状态和信息。· SENTINEL slaves <master name> 显示一个 master 的 slaves 的列表,和他们的状态。·  SENTINEL get-master-addr-by-name <master name> 返回 master 的 ip 和 port。 如果一个故障恢复正在进行或已经成功的结束,会返回升级为master的那个slave的地址。&

36、#183; SENTINEL reset <pattern> 这个命令会重新设置匹配 pattern 的 master。pattern 参数是 glob-style 的 pattern。reset 命令会清除master 之前的状态(包括正在做的故障恢复),并去掉所有的被 master 发现和关联的 slave 和 sentinel。· SENTINEL failover <master name> 强制指定的 master 进行一次故障恢复,就像当前的 master 已经联络不上一样,不需要请求其他sentinel的许可(是通过发布一个新版本的配置,从而强制

37、其他 Sentinels 跟随配置的方式实现的)。 在运行期重新配置 Sentinel (Reconfiguring Sentinel at Runtime) 从 Redis version 2.8.4 开始,Sentinel 提供了一个 API 用于加入、删除或改变 一个master 的配置。注意,如果你有多个 sentinels, 你应该应用配置变更到所有 Sentinel 实例,以使 Sentinel 正确的工作。这意味着变更一个 Sentinel 并不能使这个变更自动的传递到网络上的其他的  Sentinels 中。 下面是可以变更一个 Sent

38、inel 配置的 SENTINEL 子命令的列表:· SENTINEL MONITOR <name> <ip> <port> <quorum> 这个命令告诉Sentinel 开始监控一个 master,使用给出的IP、端口和法定人数。这个和 sentinel.conf 中的配置信息一致,只是你不能使用 hostname 作为IP,可以使用 IPv4 或 IPv6。 · SENTINEL REMOVE <name> 用于删除指定的 master:这个 master 将不再被这个 Sentinel

39、监控,并完全的从这个 Sentinel 的内部状态中删除,因此不会被 SENTINEL masters 返回,等等。·  SENTINEL SET <name> <option> <value> 这个 SET 命令与 Redis 的 CONFIG SET 命令相似,用于变更指定 master 的配置参数。在一个命令中可以指定多个配置项(或一个都没有)。所有的配置参数可以通过 sentinel.conf  或 SET 命令来设置。 下面是一个 SENTINEL SET 命令的例子,用于变更 master 的 d

40、own-after-milliseconds 配置参数:SENTINEL SET objects-cache-master down-after-milliseconds 1000 想已经说的,SENTINEL SET 可以用于设置配置文件中所有的可配置参数。更进一步,它还可以调整 master 的 法定人数(quorum)的配置信息,不需要经过添加、删除 master 的过程,仅是简单的:SENTINEL SET objects-cache-master quorum 5注意,没有提供对应的 GET 命令,因为 SENTINEL MASTER 命令可以提供全部的配置参数信息。

41、60;Pub/Sub消息(Pub/Sub Messages) 一个 client 可以使用 Sentinel 作为 Redis 兼容的 Pub/Sub 服务器(不能使用 PUBLISH命令)用于SUBSCRIBE或PSUBSCRIBE到那些通讯通道,获取指定的事件。 这个通讯通道的名字和事件的名称相同。比如,名字是 +sdown 的通讯通道的名字 能接收所有的 进入SDOWN的实例发出的相关的通知。 使用 PSUBSCRIBE * 获取全部的消息。 下面是可以接收的所有的消息通道的列表和信息的格式。 第一个词是 信息通道/事件的名称,其余部分是数据的格式

42、。注:那些 instance detailsis 指定表示这部分信息是和目标的实例相关的:<instance-type> <name> <ip> <port> <master-name> <master-ip> <master-port> 指示 master 的部分(从到最后)是可以省略的,是仅用于指定本身不是一个 master 的实例。 · +reset-master<instance details> - master 被 reset。· +sl

43、ave<instance details> - 一个新的 slave 被检测到,并被加入。· +failover-state-reconf-slaves<instance details> - 错误恢复(failover)状态 变更到 重新配置 slaves (reconf-slaves)状态。· +failover-detected<instance details> - 一个错误恢复被其他 Sentinel 启动,或任何其它 外部的事实被检测到(一个加入的 slave 被变更成 master)。· +slave-reconf

44、-sent<instance details> - 领导的 sentinel 发送 SLAVEOF 命令到这个 redis 实例以便重新配置这个新的slave。· +slave-reconf-inprog<instance details> - 这个 slave 正在被重新配置成为新 master (ip:port对表示)的 slave ,但是这个同步配置过程还没结束。· +slave-reconf-done<instance details> - 这个 slave 现在和新 master 同步了。· -dup-sen

45、tinel<instance details> - 一个或多个指定 master 的 sentinels 因为重复 被删除了(这一般在一个 Sentinel 进程重启的时候会出现)。· +sentinel<instance details> - 指定的 master 的一个新的 sentinel 被检测到并被添加。· +sdown<instance details> - 指定的实例现在成为 SDOWN 的状态。· -sdown<instance details> - 指定的实例不再是 SDOWN 的状态。&

46、#183; +odown<instance details> - 指定的实例现在成为 ODOWN 的状态。· -odown<instance details> - 指定的实例不再是 ODOWN 的状态。· +new-epoch<instance details> - 当前的代被更新了。·  +try-failover<instance details> - 一个新的故障恢复正在处理,等待主体的选举。· +elected-leader<instance details> - 指定的代赢得了主体的选举,可以执行故障恢复。· +failover-state-select-slave<instance details> - 新的故障恢复的状态是选择 slave(select-slave):选择一个适合的slave来做升级。· no-good-slave<instance details> - 没有合适的 slave 来做升级。目前我们会过些时间继续尝试,但这个有可能会改变,

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论