本申请涉及互联网技术领域,尤其涉及一种数据存储方法、装置和系统。
背景技术:
在读访问量比较大、写访问量比较少的情况下,引入分布式缓存可以减少对后端应用或数据库的访问,很大程度上降低了后端成本。但是,对于一些比较集中的数据访问请求,这些请求会集中访问到分布式缓存中的某台数据节点服务器,在有限网卡数据传输能力下,很容易导致这台数据节点服务器的网卡过载。
相关技术中,由于集中访问导致某台数据节点服务器过载后,缓存客户端会在接下来的一段时间内阻断对这台数据节点服务器的访问请求,会导致后续到达该数据节点服务器的请求出现等待或超时,对业务的可用性带来影响。
技术实现要素:
本申请旨在至少在一定程度上解决相关技术中的技术问题之一。
为此,本申请的一个目的在于提出一种数据存储方法,该方法可以将数据存储在本地缓存和远程分布式缓存中,避免将数据访问请求集中到远程分布式缓存造成的请求等待或超时问题,保证业务顺利运行。
本申请的另一个目的在于提出一种数据存储装置。
本申请的另一个目的在于提出一种数据存储系统。
为达到上述目的,本申请第一方面实施例提出的数据存储方法,包括:接收用于读取数据的读请求;在本地缓存和远程分布式缓存中查询所述读请求对应的数据;如果本地缓存和远程分布式缓存中都没有存储所述数据,则从数据库中读取所述数据;在读取到所述数据后,将所述数据写入本地缓存和远程分布式缓存中。
本申请第一方面实施例提出的数据存储方法,通过将数据写入本地缓存和远程分布式缓存,可以实现二级缓存,从而在需要读取数据时可以先在本地缓存中读取,避免集中到远程分布式缓存中读取,避免某个热点的数据节点服务器的请求出现等待或超时,避免对业务可用性带来影响,保证业务顺利运行。
为达到上述目的,本申请第二方面实施例提出的数据存储装置,包括:接收模块,用于接收用于读取数据的读请求;查询模块,用于在本地缓存和远程分布式缓存中查询所述读请求对应的数据;读取模块,用于如果本地缓存和远程分布式缓存中都没有存储所述数据,则从数据库中读取所述数据;写入模块,用于在读取到所述数据后,将所述数据写入本地缓存和远程分布式缓存中。
本申请第二方面实施例提出的数据存储装置,通过将数据写入本地缓存和远程分布式缓存,可以实现二级缓存,从而在需要读取数据时可以先在本地缓存中读取,避免集中到远程分布式缓存中读取,避免某个热点的数据节点服务器的请求出现等待或超时,避免对业务可用性带来影响,保证业务顺利运行。
为达到上述目的,本申请第三方面实施例提出的数据存储系统,包括:本申请第二方面实施例提出的数据存储装置,以及,本地缓存和远程分布式缓存,所述本地缓存和远程分布式缓存用于存储数据。
本申请第三方面实施例提出的数据存储系统,通过将数据写入本地缓存和远程分布式缓存,可以实现二级缓存,从而在需要读取数据时可以先在本地缓存中读取,避免集中到远程分布式缓存中读取,避免某个热点的数据节点服务器的请求出现等待或超时,避免对业务可用性带来影响,保证业务顺利运行。
本申请附加的方面和优点将在下面的描述中部分给出,部分将从下面的描述中变得明显,或通过本申请的实践了解到。
附图说明
本申请上述的和/或附加的方面和优点从下面结合附图对实施例的描述中将变得明显和容易理解,其中:
图1是本申请一个实施例提出的数据缓存方法的流程示意图;
图2是本申请另一个实施例提出的数据存储方法的流程示意图;
图3是图2对应的系统交互示意图;
图4是本申请一个实施例提出的失效缓存中的数据的流程示意图;
图5是图4对应的系统交互示意图;
图6是本申请一个实施例提出的数据存储装置的结构示意图;
图7是本申请另一个实施例提出的数据存储装置的结构示意图;
图8是本申请一个实施例提出的数据存储系统的结构示意图。
具体实施方式
下面详细描述本申请的实施例,所述实施例的示例在附图中示出,其中自始至终相同或类似的标号表示相同或类似的模块或具有相同或类似功能的模块。下面通过参考附图描述的实施例是示例性的,仅用于解释本申请,而不能 理解为对本申请的限制。相反,本申请的实施例包括落入所附加权利要求书的精神和内涵范围内的所有变化、修改和等同物。
图1是本申请一个实施例提出的数据缓存方法的流程示意图。
本实施例以应用服务器的执行流程为例。
参见图1,本实施例的方法包括:
s11:接收用于读取数据的读请求。
例如,调用方需要读取数据时,可以向应用服务器(appserver)发送读请求。
s12:在本地缓存和远程分布式缓存中查询所述读请求对应的数据。
其中,数据在存储时可以对应存储数据的标识和具体内容的数据,读请求中可以携带数据的标识(数据id),从而可以在存储的数据中查询是否存在读请求中携带的标识,以及,在存储该数据id时根据上述的对应关系,获取对应的数据。
应用服务器在查询数据时,可以先在本地缓存中查询再在远程分布式缓存中查询。例如,调用方在需要读取数据时,在读请求中可以携带数据id,应用服务器接收到读请求后,可以先在本地缓存中查询是否存储该数据id,如果没有存储,则可以在远程分布式缓存中查询是否存在该数据id,如果也没有存储,可以确定本地缓存和远程分布式缓存都没有存储调用方需要读取的数据。
进一步的,本地缓存中可以对使用频率低于预设值的数据进行过期处理,例如,采用近期最少使用(leastrecentlyused,lru)算法进行过期处理。
其中,lru时内存管理的一种页面置换算法,对于在内存中但又不用的数据块(内存块)叫做lru,操作系统会根据哪些数据属于lru而将其移出内存 而腾出空间来加载另外的数据。
通过在本地缓存中将使用频率低于预设值的数据进行过期处理,可以淘汰使用频率低的数据,从而经过一段时间的运行,热点数据会在本地大量的缓存,可以降低对远程分布式缓存的访问。
s13:如果本地缓存和远程分布式缓存中都没有存储所述数据,则从数据库读取所述数据。
应用服务器在确定本地缓存和远程分布式缓存中都没有存储调用方需要的数据时,可以向数据库发送携带该数据id的读请求,以从数据库中读取该数据id对应的数据,获取调用方需要的数据。
s14:在读取到所述数据后,将所述数据写入本地缓存和远程分布式缓存中。
应用服务器在从数据库中读取到该数据后,以二级缓存的方式,在本地缓存和远程分布式缓存中都存储该数据。
本实施例中,通过将数据写入本地缓存和远程分布式缓存,可以实现二级缓存,从而在需要读取数据时可以先在本地缓存中读取,避免集中到远程分布式缓存中读取,避免某个热点的数据节点服务器的请求出现等待或超时,避免对业务可用性带来影响,保证业务顺利运行。进一步的,通过在本地缓存中对使用频率较低的数据进行过期处理,可以将热点数据积累在本地缓存中,降低对远程分布式缓存的访问。
上述实施例给出了本地缓存和远程分布式缓存中都不存在需要的数据时的处理流程,当本地缓存或远程分布式缓存中存在需要的数据时,可以执行其他流程。具体参见下述实施例。
图2是本申请另一个实施例提出的数据存储方法的流程示意图。图3是图 2对应的系统交互的示意图。
参见图2,该方法包括:
s201:应用服务器接收读请求,该读请求中携带数据id。
其中,读请求是调用方发送的用于读取数据的请求。
参见图3,应用服务器上可以部署虚拟内存(virtualmemory,vm),vm中包括处理模块和缓存模块,缓存模块包括本地缓存和远程分布式缓存客户端(简称为缓存客户端),远程分布式缓存系统中包括多个数据节点服务器(datanodeserver)。
具体的,调用方发送的读请求是应用服务器的处理模块接收到的。
之后,处理模块接收到读请求后,向缓存模块查询读请求中携带的数据id对应的数据,如果缓存模块中存储该数据id对应的数据,则缓存模块将该数据返回给处理模块,并由处理模块返回给调用方。如果缓存模块中没有存储该数据id对应的数据,则缓存模块向处理模块返回结果是空的消息,处理模块接收到该消息后,向数据库发送携带该数据id的读请求,从数据库中获取该数据并返回给调用方。
其中,本地缓存和远程分布式缓存中任一个存储该数据id对应的数据时,缓存模块返回给处理模块的结果包括该数据id对应的数据,本地缓存和远程分布式缓存中都没有存储该数据id对应的数据时,缓存模块返回结果是空的消息。
具体的,参见图2,该方法还包括:
s202:应用服务器在本地缓存中查询是否存储读请求中携带的数据id,若是,执行s203,否则,执行s204。
其中,本地缓存在存储数据时,可以对应存储数据id和具体内容的数据, 从而可以先在本地缓存中查询是否存储读请求中携带的数据id。
s203:应用服务器在本地缓存中获取数据id对应的数据,并返回给调用方。
其中,本地缓存中可以对应存储数据id及具体内容的数据,因此,根据该对应关系,可以获取读请求中携带的数据id对应的数据。
具体的,本地缓存中在缓存数据时,可以采用map数据结构。
其中,map是一种数据结构,是指以键值对(key-value)的形式存储数据。在本实施例中,key可以具体是数据id,value是具体内容的数据。
本地缓存中的过期策略可以采用lru算法或者采用guavacache机制,自定义过期策略,对使用频率低于预设值的数据进行过期处理。
其中,lru时内存管理的一种页面置换算法,对于在内存中但又不用的数据块(内存块)叫做lru,操作系统会根据哪些数据属于lru而将其移出内存而腾出空间来加载另外的数据。
guavacache是一种本地缓存实现,支持多种缓存过期策略。
通过在本地缓存中将使用频率低于预设值的数据进行过期处理,可以淘汰使用频率低的数据,从而经过一段时间的运行,热点数据会在本地大量的缓存,可以降低对远程分布式缓存的访问。
s204:应用服务器在远程分布式缓存中查询是否存储读请求中携带的数据id,若是,执行s205,否则,执行s206。
具体的,如图3所示,缓存客户端用于计算路由规则(routerule),确定读请求中携带的数据id属于的数据节点服务器,并在对应的数据节点服务器中查询是否存储该数据id对应的数据。其中,每个数据节点服务器可以存储预设范围的数据id对应的数据。
处理模块接收到调用方发送的携带数据id的读请求后,向缓存模块转发该读请求,缓存模块接收到该读请求后,先在本地缓存中查询是否存在该数据id,如果不存在,缓存模块中的缓存客户端计算路由规则,确定该数据id属于的数据节点服务器,比如,该数据id属于第一范围,而第一范围的数据是第一数据节点服务器存储的,则该数据id属于的数据节点服务器是第一数据节点服务器。以该数据id属于的数据节点服务器是第一数据节点服务器为例,之后,缓存客户端可以将携带该数据id的读请求发送给第一数据节点服务器,第一数据节点服务器可以查询自身是否存储该数据id,以根据查询结果进行相应处理。
s205:应用服务器在远程分布式缓存中获取该数据id对应的数据,将该数据写入本地缓存中,并返回给调用方。
例如,第一数据节点服务器中存储该数据id后,可以根据存储的数据id与数据之间的对应关系,获取该数据id对应的数据,并发送给应用服务器内的缓存客户端。
缓存客户端接收到第一数据节点服务器发送的数据后,可以将该数据写入本地缓存中。以及,本地缓存将该数据返回给处理模块,由处理模块返回给调用方。
s206:应用服务器在数据库中获取该数据id对应的数据。
例如,如果本地缓存和远程分布式缓存中都没有该数据id对应的数据时,缓存模块会向处理模块返回结果是空的消息。
处理模块接收到该结果是空的消息后,向数据库发送携带该数据id的读请求,数据库可以根据存储的数据id与数据间的对应关系,获取该数据id对应的数据并返回给应用服务器中的处理模块。
s207:应用服务器将该数据写入本地缓存和远程分布式缓存中。
例如,处理模块接收到数据库返回的数据后,将其写入缓存模块。缓存模块在处理时,一方面将该数据写入本地缓存,另一方面,由缓存客户端计算路由规则,确定远程分布式缓存系统中对应的数据节点服务器,并将该数据写入对应的数据节点服务器。
本实施例中,通过在本地缓存和远程分布式缓存中都没有存储需要的数据时,从数据库中读取数据,并写入本地缓存和远程分布式缓存,可以实现二级缓存,以便在读取数据时,可以先从本地缓存中读取,避免将读取数据的请求集中到远场分布式缓存中,保证业务顺利运行。另外,当远程分布式缓存中存储有本地缓存中没有的数据时,可以从远程分布式缓存中获取数据并写入本地缓存中,以方便后续从本地缓存中获取数据。另外,在本地缓存中对使用频率低于预设值的数据进行过期处理,可以使得热点数据在本地大量的缓存,降低对远程分布式缓存的访问。
在数据存储后,会出现数据更新的情况,在发生数据更新时,可以采用如下的方式失效本地缓存和远程分布式缓存中的数据。
图4是本申请一个实施例提出的失效缓存中的数据的流程示意图。图5是图4对应的系统交互示意图。
参见图4,本实施例的方法包括:
s401:应用服务器在数据发生更新后,更新数据库中存储的数据。
其中,数据更新可以是由应用(app)发起的,某个app在数据更新后,可以将更新后的数据发送给应用服务器的处理模块,处理模块接收到更新后的数据后,更新数据库中相应的数据。
例如,第一数据id的数据发生了更新(由a更新为a’),则应用服务器 可以向数据库发送写请求,写请求中包括第一数据id和更新后的数据a’,数据库接收到该写请求后,将第一数据id对应的数据从a更新为a’。
在数据发生更新后,应用服务器一方面可以更新数据库中的数据,另一方面,还可以对本地缓存和远程分布式缓存中存储的发生更新的数据进行失效处理。具体的失效处理的流程可以包括:
s402:应用服务器向消息服务器发送数据更新的变动通知。
其中,变动通知中可以携带发生更新的数据id,如第一数据发生更新,则可以携带第一数据的数据id,假设用第一数据id表示。
s403:消息服务器向所有的应用服务器发送组播消息。
其中,消息服务器接收到上述的变动通知后,以组播方式向所有应用服务器发送用于指示数据失效的消息,以失效相应的数据。
消息服务器发送的组播消息中携带发生变更的数据id,如第一数据id,以失效第一数据。
s404:应用服务器接收到该组播消息后,失效本地缓存中的发生更新的数据。
其中,每个应用服务器接收到组播消息后,可以从该消息中解析出数据id,并在本地缓存中失效该数据id及对应的数据。
s405:应用服务器失效远程分布式缓存中的发生更新的数据。
其中,每个应用服务器接收到组播消息后,不仅失效本地缓存中的相应数据,还需要对远场分布式缓存中的数据进行失效处理。
具体的,失效远程分布式缓存中的数据的流程可以包括:
确定存储所述数据的远程分布式缓存中的数据节点服务器;
向所述数据节点服务器发送携带所述数据的标识的消息,以使所述数据节 点服务器接收到所述消息后,根据所述标识失效所述数据。
例如,处理模块接收到组播消息后,向缓存模块发送携带第一数据id的失效指令,缓存模块接收到该失效指令后,一方面在本地缓存中失效第一数据id及对应的第一数据,另一方面,由缓存模块中的缓存客户端确定第一数据id属于的数据节点服务器(假设是第一数据节点服务器),则缓存客户端向第一数据节点服务器发送携带第一数据id的失效指令,第一数据节点服务器接收到该失效指令后,失效第一数据节点服务器内存储的第一数据id及对应的第一数据。
本实施例以每个应用服务器都失效远程分布式缓存中的数据为例,可以理解的是,也可以根据预设算法在所有的应用服务器中确定出一个应用服务器,由该一个应用服务器进行远程分布式缓存中数据的失效,而具体的确定某个应用服务器的算法不限定。
进一步的,当本地缓存和远程分布式缓存中的数据都失效后,后续如果需要读取该数据,由于都失效,则无法从本地缓存和远程分布式缓存中读取到该数据,之后调用方需要从数据库中读取数据,并写入本地缓存和远程分布式缓存中,从而实现本地缓存和远程分布式缓存中数据的更新,并与数据库中的数据保持一致。
本实施例中,通过在发生数据更新时,失效本地缓存和远程分布式缓存中的相应数据,可以在后续读取该数据时,重新从数据库中读取数据,并将重新读取的数据写入本地缓存和远程分布式缓存中,实现了本地缓存和远程分布式缓存中的数据更新,并和数据库中的数据保持一致。另外,本实施例在失效数据时,通过消息服务器采用组播方式进行消息推送,可以提高处理效率。
图6是本申请一个实施例提出的数据存储装置的结构示意图。
本实施例的装置可以位于应用服务器中。具体可以对应上述实施例中的处理模块。
参见图6,该装置60包括:接收模块61、查询模块62、读取模块63和写入模块64。
接收模块61用于接收用于读取数据的读请求。
例如,调用方需要读取数据时,可以向应用服务器(appserver)发送读请求。
查询模块62用于在本地缓存和远程分布式缓存中查询所述读请求对应的数据。
其中,数据在存储时可以对应存储数据的标识和具体内容的数据,读请求中可以携带数据的标识(数据id),从而可以在存储的数据中查询是否存在读请求中携带的标识,以及,在存储该数据id时根据上述的对应关系,获取对应的数据。
可选的,查询模块62具体用于:
先在本地缓存中查询所述读请求对应的数据;
如果本地缓存中不存在所述数据,则在远程分布式缓存中查询所述数据。
例如,调用方在需要读取数据时,在读请求中可以携带数据id,应用服务器接收到读请求后,可以先在本地缓存中查询是否存储该数据id,如果没有存储,则可以在远程分布式缓存中查询是否存在该数据id,如果也没有存储,可以确定本地缓存和远程分布式缓存都没有存储调用方需要读取的数据。
读取模块63用于如果本地缓存和远程分布式缓存中都没有存储所述数据,则从数据库中读取所述数据。
应用服务器在确定本地缓存和远程分布式缓存中都没有存储调用方需要 的数据时,可以向数据库发送携带该数据id的读请求,以从数据库中读取该数据id对应的数据,获取调用方需要的数据。
写入模块64用于在读取到所述数据后,将所述数据写入本地缓存和远程分布式缓存中。
应用服务器在从数据库中读取到该数据后,以二级缓存的方式,在本地缓存和远程分布式缓存中都存储该数据。
另外,一些实施例中,本地缓存用于:如果远程分布式缓存中存在所述数据,从远程分布式缓存中获取并存储所述数据。
一些实施例中,参见图7,该装置60还包括:
更新模块65,用于在所述数据发生更新后,更新数据库中存储的所述数据。
其中,数据更新可以是由应用(app)发起的,某个app在数据更新后,可以将更新后的数据发送给应用服务器的处理模块,处理模块接收到更新后的数据后,更新数据库中相应的数据。
例如,第一数据id的数据发生了更新(由a更新为a’),则应用服务器可以向数据库发送写请求,写请求中包括第一数据id和更新后的数据a’,数据库接收到该写请求后,将第一数据id对应的数据从a更新为a’。
失效模块66,用于对本地缓存和远程分布式缓存中存储的所述数据进行失效处理。
在数据发生更新后,应用服务器一方面可以更新数据库中的数据,另一方面,还可以对本地缓存和远程分布式缓存中存储的发生更新的数据进行失效处理。
进一步的,参见图7,失效模块66包括:
第一单元661,用于向消息服务器发送数据更新的变动通知,以使所述消息服务器接收到所述变动通知后,向所有应用服务器发送组播消息。
其中,变动通知中可以携带发生更新的数据id,如第一数据发生更新,则可以携带第一数据的数据id,假设用第一数据id表示。
其中,消息服务器接收到上述的变动通知后,以组播方式向所有应用服务器发送用于指示数据失效的消息,以失效相应的数据。
消息服务器发送的组播消息中携带发生变更的数据id,如第一数据id,以失效第一数据。
第二单元662,用于接收到所述组播消息后失效本地缓存中存储的所述数据。
其中,每个应用服务器接收到组播消息后,可以从该消息中解析出数据id,并在本地缓存中失效该数据id及对应的数据。
第三单元663,用于失效远程分布式缓存中存储的所述数据。
其中,每个应用服务器接收到组播消息后,不仅失效本地缓存中的相应数据,还需要对远场分布式缓存中的数据进行失效处理。
可选的,所述第三单元663具体用于:
确定存储所述数据的远程分布式缓存中的数据节点服务器;
向所述数据节点服务器发送携带所述数据的标识的消息,以使所述数据节点服务器接收到所述消息后,根据所述标识失效所述数据。
例如,处理模块接收到组播消息后,向缓存模块发送携带第一数据id的失效指令,缓存模块接收到该失效指令后,一方面在本地缓存中失效第一数据id及对应的第一数据,另一方面,由缓存模块中的缓存客户端确定第一数据id属于的数据节点服务器(假设是第一数据节点服务器),则缓存客户端向第 一数据节点服务器发送携带第一数据id的失效指令,第一数据节点服务器接收到该失效指令后,失效第一数据节点服务器内存储的第一数据id及对应的第一数据。
进一步的,当本地缓存和远程分布式缓存中的数据都失效后,后续如果需要读取该数据,由于都失效,则无法从本地缓存和远程分布式缓存中读取到该数据,之后调用方需要从数据库中读取数据,并写入本地缓存和远程分布式缓存中,从而实现本地缓存和远程分布式缓存中数据的更新,并与数据库中的数据保持一致。
进一步的,本地缓存可以采用lru算法或者采用guava的cache机制,对使用频率低于预设值的数据进行过期处理。
可以理解的是,本实施例与上述方法实施例对应,具体内容可以参见方法实施例,在此不再详细说明。
本实施例中,通过将数据写入本地缓存和远程分布式缓存,可以实现二级缓存,从而在需要读取数据时可以先在本地缓存中读取,避免集中到远程分布式缓存中读取,避免某个热点的数据节点服务器的请求出现等待或超时,避免对业务可用性带来影响,保证业务顺利运行。
图8是本申请一个实施例提出的数据存储系统的结构示意图。参见图8,该系统80包括数据存储装置81、本地缓存82和远程分布式缓存83。
其中,数据存储装置可以如图6或图7所示,本地缓存和远程分布式缓存用于存储数据。
进一步的,本地缓存可以对使用频率低于预设值的数据进行过期处理,以在本地缓存中积累热点数据,降低对远程分布式缓存的访问。
本实施例中,通过将数据写入本地缓存和远程分布式缓存,可以实现二级 缓存,从而在需要读取数据时可以先在本地缓存中读取,避免集中到远程分布式缓存中读取,避免某个热点的数据节点服务器的请求出现等待或超时,避免对业务可用性带来影响,保证业务顺利运行。
需要说明的是,在本申请的描述中,术语“第一”、“第二”等仅用于描述目的,而不能理解为指示或暗示相对重要性。此外,在本申请的描述中,除非另有说明,“多个”的含义是指至少两个。
流程图中或在此以其他方式描述的任何过程或方法描述可以被理解为,表示包括一个或更多个用于实现特定逻辑功能或过程的步骤的可执行指令的代码的模块、片段或部分,并且本申请的优选实施方式的范围包括另外的实现,其中可以不按所示出或讨论的顺序,包括根据所涉及的功能按基本同时的方式或按相反的顺序,来执行功能,这应被本申请的实施例所属技术领域的技术人员所理解。
应当理解,本申请的各部分可以用硬件、软件、固件或它们的组合来实现。在上述实施方式中,多个步骤或方法可以用存储在存储器中且由合适的指令执行系统执行的软件或固件来实现。例如,如果用硬件来实现,和在另一实施方式中一样,可用本领域公知的下列技术中的任一项或他们的组合来实现:具有用于对数据信号实现逻辑功能的逻辑门电路的离散逻辑电路,具有合适的组合逻辑门电路的专用集成电路,可编程门阵列(pga),现场可编程门阵列(fpga)等。
本技术领域的普通技术人员可以理解实现上述实施例方法携带的全部或部分步骤是可以通过程序来指令相关的硬件完成,所述的程序可以存储于一种计算机可读存储介质中,该程序在执行时,包括方法实施例的步骤之一或其组合。
此外,在本申请各个实施例中的各功能单元可以集成在一个处理模块中,也可以是各个单元单独物理存在,也可以两个或两个以上单元集成在一个模块中。上述集成的模块既可以采用硬件的形式实现,也可以采用软件功能模块的形式实现。所述集成的模块如果以软件功能模块的形式实现并作为独立的产品销售或使用时,也可以存储在一个计算机可读取存储介质中。
上述提到的存储介质可以是只读存储器,磁盘或光盘等。
在本说明书的描述中,参考术语“一个实施例”、“一些实施例”、“示例”、“具体示例”、或“一些示例”等的描述意指结合该实施例或示例描述的具体特征、结构、材料或者特点包含于本申请的至少一个实施例或示例中。在本说明书中,对上述术语的示意性表述不一定指的是相同的实施例或示例。而且,描述的具体特征、结构、材料或者特点可以在任何的一个或多个实施例或示例中以合适的方式结合。
尽管上面已经示出和描述了本申请的实施例,可以理解的是,上述实施例是示例性的,不能理解为对本申请的限制,本领域的普通技术人员在本申请的范围内可以对上述实施例进行变化、修改、替换和变型。