著录项信息
专利名称 | 获取动态Feed索引的方法和系统 |
申请号 | CN201110439565.6 | 申请日期 | 2011-12-23 |
法律状态 | 授权 | 申报国家 | 中国 |
公开/公告日 | 2013-06-26 | 公开/公告号 | CN103177027A |
优先权 | 暂无 | 优先权号 | 暂无 |
主分类号 | G06F17/30 | IPC分类号 | G;0;6;F;1;7;/;3;0查看分类表>
|
申请人 | 北京新媒传信科技有限公司 | 申请人地址 | 北京市海淀区万泉庄路28号万柳新贵大厦A座6层602室
变更
专利地址、主体等相关变化,请及时变更,防止失效 |
权利人 | 北京新媒传信科技有限公司 | 当前权利人 | 北京新媒传信科技有限公司 |
发明人 | 国兴旺 |
代理机构 | 北京市隆安律师事务所 | 代理人 | 权鲜枝 |
摘要
本发明公开了一种获取动态Feed索引的方法和系统,能够在高并发查询和索引表的数据量较大的场景下得到较佳的查询性能。本发明实施例提供的获取动态Feed索引的方法,采用键值对存储结构建立索引表缓存,所述索引表缓存中的Feed索引与关系型数据库中的相应Feed索引一致,该方法包括:客户端服务器向索引表缓存和关系型数据库发送查询请求;客户端服务器将索引表缓存和关系型数据库中先返回的查询结果作为所获取的Feed索引。
1.一种获取动态Feed索引的方法,其特征在于,采用键值对存储结构建立索引表缓存,所述索引表缓存中的Feed索引与关系型数据库中的相应Feed索引一致;所述方法包括:
客户端服务器向索引表缓存和关系型数据库发送查询请求;
客户端服务器将索引表缓存和关系型数据库中先返回的查询结果作为所获取的Feed索引;
其中,所采用的键值对存储结构为Redis存储系统中的有序集合结构,所述有序集合结构包括哈希表和跳跃表,
所述哈希表中存放用户与优先级的映射,该优先级设置为用户的动态标识FeedId;
所述跳跃表中存放根据所述优先级排序后的所有用户的Feed索引。
2.根据权利要求1所述的方法,其特征在于,所述方法还包括:
若客户端服务器接收到的先返回的查询结果来自索引表缓存,则客户端服务器丢弃接收到的关系型数据库返回的查询结果;
若客户端服务器接收到的先返回的查询结果来自关系型数据库,则客户端服务器丢弃接收到的索引表缓存返回的查询结果;当客户端服务器没有接收到索引表缓存返回的查询结果或者接收到索引表缓存返回的内容为空的消息时,采用批量填充的方式将查询结果中的Feed索引填充至索引表缓存。
3.根据权利要求1所述的方法,其特征在于,根据用户标识在多个索引表缓存中分片存储Feed索引,以及,根据用户标识在多个关系型数据库中分片存储Feed索引,在客户端服务器向索引表缓存和关系型数据库发送查询请求之前,所述方法还包括:
客户端服务器根据该查询请求中所包括的用户标识,在多个索引表缓存中选取相应的索引表缓存,并在多个关系型数据库中选取相应的关系型数据库,客户端服务器向所选取的索引表缓存和所选取的关系型数据库发送查询请求。
4.根据权利要求1所述的方法,其特征在于,查询索引表缓存得到查询结果的方法包括:
根据查询请求中的用户标识获取到用户的偏移量,所述偏移量指示当前所需获取索引表时的起始位置,所述查询请求中包括用户标识和查询内容指示信息;
根据查询请求中的查询内容指示信息,在相应的索引表中从所述起始位置开始提取预定条数的Feed索引,作为查询结果,其中,所述索引表为新动态索引表或者时间线索引表。
5.根据权利要求4所述的方法,其特征在于,所述根据查询请求中的用户标识获取到用户的偏移量包括:
索引表缓存根据用户标识通过zrevrank命令获取到用户的偏移量;
所述根据查询请求中的查询内容指示信息,在相应的索引表中从所述起始位置开始提取预定条数的Feed索引,作为查询结果包括:
索引表缓存根据查询内容指示信息通过zrevrange命令在相应的索引表中从所述起始位置开始提取预定条数的Feed索引,作为查询结果。
6.根据权利要求1所述的方法,其特征在于,所述方法还包括:
在索引表缓存中设置滑动过期阈值;
当一个用户的Feed索引在索引表缓存中的存放时间超过所述滑动过期阈值时,删除该用户在索引表缓存中的Feed索引。
7.根据权利要求2所述的方法,其特征在于,所述方法还包括:
客户端服务器向索引表缓存发送请求,请求索引表缓存将一个新用户的Feed索引插入到索引表缓存或请求索引表缓存在已有用户的Feed索引中插入新的Feed索引;以及,客户端服务器向关系型数据库发送请求,请求关系型数据库将一个新用户的Feed索引插入到关系型数据库或请求关系型数据库在已有用户的Feed索引中插入新的Feed索引。
8.一种获取动态Feed索引的系统,其特征在于,所述系统中设置有采用键值对存储结构建立索引表缓存,所述系统还包括关系型数据库和客户端服务器,
所述索引表缓存中的Feed索引与关系型数据库中的相应Feed索引一致;
所述客户端服务器向索引表缓存和关系型数据库发送查询请求,并将索引表缓存和关系型数据库中先返回的查询结果作为所获取的Feed索引;
其中索引表缓存采用的键值对存储结构为Redis存储系统中的有序集合结构,所述有序集合结构的哈希表中存放用户与优先级的映射,该优先级设置为用户的动态标识FeedId,所述有序集合结构的跳跃表中存放根据所述优先级排序后的所有用户的Feed索引。
9.根据权利要求8所述的系统,其特征在于,
若客户端服务器接收到的先返回的查询结果来自索引表缓存,则客户端服务器丢弃接收到的关系型数据库返回的查询结果;
若客户端服务器接收到的先返回的查询结果来自关系型数据库,则客户端服务器丢弃接收到的索引表缓存返回的查询结果;当客户端服务器没有接收到索引表缓存返回的查询结果或者接收到索引表缓存返回的内容为空的消息时,采用批量填充的方式将查询结果中的Feed索引填充至索引表缓存。
获取动态Feed索引的方法和系统\n技术领域\n[0001] 本发明涉及以用户动态为业务核心的互联网技术领域,特别涉及一种获取动态Feed索引的方法和系统。\n背景技术\n[0002] 随着社交网络(如国外的facebook,国内的renren网)、微博(如国外的twitter,国内的新浪网博)等以用户的动态(Feed)内容为中心的互联网产品的兴起,如何对海量的数据进行存储和快速查询到用户的Feed列表已经被越来越多的技术人员或产品人员所关注,成为研究的一个重要课题;而系统查询的响应速度会直接影响到最终用户的体验,成为这类互联网产品的实现或性能优化的一个突出问题。\n[0003] 这类互联网产品的一个共同特点就是以用户Feed(或称为用户生成内容)为数据核心,之后建立用户与Feed的索引表,如新动态(NewsFeed)或时间线(Timelines)关系表,用户阅读时根据一定的条件查询这些关系表(索引表),把对应的可阅读Feed的主键(Key)集合查找出来,之后再根据这些主键集合批量提取Feed内容组成可阅读的Feed列表,供用户消费。\n[0004] 现有方案中一般会使用关系型数据库(如数据库mysql)中的一张或多张结构相似的数据表来存储索引表,每次在查询索引表时,需要利用结构化查询语言(Structured Query Language,SQL)对查询语句进行解析(Parse),根据解析结果得到所需查询的索引表。\n[0005] 然而,现有获取Feed的索引表至少具有如下缺陷:\n[0006] 现有大量的Feed索引表的查询依赖于关系型数据库,在高并发查询和索引表的数据量较大的场景会导致查询性能急剧降低,尤其对使用mysql这种关系型数据库的场景,每次查询都要进行查询语句的SQL解析,会严重影响系统的性能,导致响应缓慢。\n[0007] 现有这种只依赖于关系型数据库的查询方案,已经越来越不能满足高并发和海量数据的查询需求,成为整个业务系统的性能瓶颈。\n发明内容\n[0008] 本发明实施例提供了一种获取动态Feed索引的方法和系统,以解决现有方案依赖于关系型数据库的查询,无法满足高并发和海量数据的查询需求的问题。\n[0009] 为达到上述目的,本发明实施例采用了如下技术方案:\n[0010] 本发明实施例提供了一种获取动态Feed索引的方法,采用键值对存储结构建立索引表缓存,所述索引表缓存中的Feed索引与关系型数据库中的相应Feed索引一致;所述方法包括:\n[0011] 客户端服务器向索引表缓存和关系型数据库发送查询请求;\n[0012] 客户端服务器将索引表缓存和关系型数据库中先返回的查询结果作为所获取的Feed索引。\n[0013] 本发明实施例还提供了一种获取动态Feed索引的系统,所述系统中设置有采用键值对存储结构建立索引表缓存,所述系统还包括关系型数据库和客户端服务器,[0014] 所述索引表缓存中的Feed索引与关系型数据库中的相应Feed索引一致;\n[0015] 所述客户端服务器向索引表缓存和关系型数据库发送查询请求,并将索引表缓存和关系型数据库中先返回的查询结果作为所获取的Feed索引。\n[0016] 本发明实施例的有益效果是:\n[0017] 本发明实施例提供了一种新型的并行查询机制,同时使用所设置的索引表缓存和关系型数据库查询数据,使用先返回的查询结果,不但保证了查询的快速响应,也避免了对关系型数据库的依赖,无需在每次查询时进行SQL解析,从而保证了在高并发查询和索引表的数据量较大的场景下也能得到较佳的查询性能。\n[0018] 进一步的,本发明实施例通过缓存操作减少了磁盘的I/O操作,降低了数据访问的压力,以尽可能降低Feed索引的查询业务对系统中其他业务的影响,保证了系统整体性能的稳定。\n附图说明\n[0019] 图1为本发明实施例一提供的获取Feed索引的方法流程示意图;\n[0020] 图2为采用线性方式访问的方法流程示意图;\n[0021] 图3为Redis存储系统中内存管理的原理示意图;\n[0022] 图4为本发明实施例二提供的获取Feed索引的方法流程示意图;\n[0023] 图5为本发明实施例三提供的获取动态Feed索引的系统结构示意图。\n具体实施方式\n[0024] 为使本发明的目的、技术方案和优点更加清楚,下面将结合附图对本发明实施方式作进一步地详细描述。\n[0025] 本发明实施例的主要技术构思在于在社交网络(SNS)或微博中利用缓存服务器Redis来实现多维度的用户和Feed关系的索引表缓存(Indexes cache),以提高查询效率的目的。\n[0026] 参见图1,为本发明实施例一提供的获取动态(Feed)索引的方法。\n[0027] 11a:客户端(Client)服务器向索引表缓存发送查询请求(如call1)。\n[0028] 本发明实施例中采用键值对(Key-Value)存储结构建立上述索引表缓存,具有键值对存储结构的索引表缓存属于一种非关系型数据库,从而避免了关系型数据库在每次查询时都需要进行的SQL解析,保证了查询速度。所述索引表缓存中的Feed索引与关系型数据库(如mysql)中的相应Feed索引一致,即关系型数据库中的Feed索引包括索引表缓存中的Feed索引,也包括除索引表缓存中的Feed索引之外的其他Feed索引。可以理解,索引表缓存中除了Feed索引之外还可以包括其他的信息。\n[0029] 本实施例中的索引表可以包括多个维度的关系型索引表,例如,NewsFeed和Timelines。Timelines用来显示用户已关注的人所发的Feed的列表,其按照时间倒序。\nNewsFeed用来显示用户自己发布的Feed的列表,这些所发布的Feed实际上是要进入关注这个用户的其他用户的Timelines中,这个过程对于大多数用户来说会通过系统的分发过程实现。\n[0030] 参见如下表1,显示了NewsFeed索引表和Timelines索引表所采用的一种结构。\n[0031] 表1\n[0032] \n[0033] 表1中的UserId为用户的唯一标识,FeedId为Feed的唯一标识,FeedId的生成规则为按照时间递增,由应用程序进行控制。CreateTime为此条数据记录生成的时间,表中还可以包括一些其他字段,在此略去。\n[0034] 索引表缓存和关系型数据库中存储的Feed的索引,Feed的具体内容存储在非关系型数据库中,如存储在数据库nosql或mysql+handlersocket数据库的非关系型内容表中,参见表2。\n[0035] 表2\n[0036] \n FeedId 内容(Content) CreateTime OtherFields\n 5514194530754113613 内容1 2011-08-3102:44:50 ...\n 5514194584722223189 内容2 2011-08-3102:44:50 ...\n 5514195330536583335 内容3 2011-08-3102:46:30 ...\n ... ... ... ...\n[0037] 其中,FeedId为Feed的唯一标识,Content列存储的是Feed的真实内容,格式可以自定义,例如JSON(JavaScript Object Notation)格式或Protobuf压缩格式等。\nCreateTime为此条Feed生成的时间,表中还可以包括一些其他字段,在此略去。\n[0038] 11b:客户端服务器在向索引表缓存发送查询请求的同时,向关系型数据库发送查询请求(如call2)。\n[0039] 上述步骤11和12中客户端服务器发送至索引表缓存和关系型数据库的查询命令可以都采用异步查询指令。\n[0040] 进一步的,本实施例中还提供了一种分片处理机制,设置多个索引表缓存和多个关系型数据库,每个索引表缓存和关系型数据库中分别存储相应的部分Feed索引。这种分片处理机制同样可以应用在非关系型数据库中。\n[0041] 分片规则可以如下:由于关系型数据库存储的是索引表,与用户相关,所以可以按照UserId进行分片,如将UserId结尾为奇数的Feed索引存储在mysql01上,将UserId结尾为偶数的Feed索引存储在mysql02上。\n[0042] 对索引表缓存,当利用Redis实现索引表缓存时,可以通过Redis内置的一致性Hash算法来实现,如将查询请求中的UserId和维度信息作为Key,将由该Key得到的Value对应于相应的索引表缓存。\n[0043] 对于非关系型数据库,其存储的是Feed的内容,按照Key-Value方式进行访问,Key即为FeedId,Value存储的可以认为是内容表中除FeedId之外剩余的其他字段,所以可以按照FeedId进行分片,例如FeedId小于10000000000000的Feed内容存储noql03上,FeedId大于10000000000000的Feed内容存储在nosql04上。\n[0044] 客户端服务器接收来自客户端的查询请求,该查询请求中可以包括用户标识(UserId),客户端服务器根据该查询请求在多个索引表缓存中选取相应的索引表缓存,并在多个关系型数据库中选取相应的关系型数据库,客户端服务器向所选取的索引表缓存和所选取的关系型数据库发送查询请求。\n[0045] 在获取到Feed索引后,客户端服务器可以根据动态标识(FeedId)在多个非关系型数据库选取相应的数据库,并从该数据库中获取到Feed内容。非关系型数据中存储的Feed内容会根据索引表缓存中存储的Feed索引进行变化。例如,本方案中还可以实现对索引表缓存中Feed索引的追加,以满足业务需要。当系统中增加了一个新的用户时,非关系型数据库将新用户的Feed内容写入内容表的Content中。相应的,客户端服务器向关系型数据库和索引表缓存发送请求,请求追加索引,则关系型数据库利用SQL命令将新用户的Feed索引插入该数据库的索引表中,索引表缓存利用zadd命令将新用户的Feed索引插入该缓存的索引表中。\n[0046] 12:客户端服务器将索引表缓存和关系型数据库中先返回的查询结果作为所获取的Feed索引。\n[0047] 当关系型数据库和索引表缓存中都存在所查询的Feed索引时,关系型数据库会对接收到的查询请求返回(Return)查询结果(如表示为Value2),索引表缓存也会对接收到的查询请求返回查询结果(如表示为Value1),则使用先返回的查询结果,而后返回的查询结果将不再被采用且最终将会被丢弃。\n[0048] 由上可见,本实施例采用了一种并行的查询机制,首先返回的定为有效数据,后返回的会执行剩余部分流程后(若需要时)被丢弃掉,这样可以保证快速的响应,从而改进了一般的线性方式访问带来的等待时间长的问题,参见图2,显示了线性方式访问的方法流程示意图,这种方式下,首先访问索引表缓存,当索引表缓存中没有所要查询的Feed索引后,例如,索引表缓存返回的消息内容为空(null)时,再去关系型数据库中查询,这种方式下,增加了缓存没有命中时再去请求数据库时间开销。本方案通过采用并行查询机制解决了这种等待时间过长的问题,保证了查询的快速响应。\n[0049] 进一步的,上述的索引表缓存采用Redis存储系统中的有序集合(Sorted Set)结构。Redis是一个Key-Value存储系统。和Memcached存储系统类似,它支持存储的Value类型相对更多,包括String(字符串)、Hash(哈希)、List(链表)、Set(集合)和Sorted set(有序集合)。这些数据类型都支持入栈/出栈(push/pop)、增加/移除(add/remove)和取交集、并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,Redis支持各种不同方式的排序。为了保证效率,Redis将数据缓存在内存中,并且,Redis还具有多种Memcached缺少的功能,例如,Redis能够周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了主从(Master-Slave)同步,优选的,本方案上述的索引表缓存采用Redis实现,从而能够利用Redis的周期性写入或修改的功能等来提高索引表缓存的性能。\n[0050] 进一步的,本方案采用Redis中的有序集合结构,为了便于清楚地说明本方案,下面对所涉及的Redis的关键技术点进行说明。\n[0051] 参见图3,显示了Redis存储系统中内存管理的原理示意图。\n[0052] 首先Redis内部使用一个redis核心对象(redisObject)来表示所有的key和value,redisObject最主要的信息如图3所示:数据类型(type)代表一个value对象具体是何种数据结构类型,编码方式(encoding)是不同数据类型在Redis内部的存储方式,可以包括原始(raw)类型、整型int、哈希(ht)结构、zipmap结构、linkedlist结构、ziplist结构、intset结构。\n[0053] 比如,对type=string,其代表value存储的是一个普通字符串,那么对应的encoding可以是raw或者是int,如果是int则代表实际Redis内部是按数值型类存储和表示这个字符串的(当然前提是这个字符串本身可以用数值表示),如″123″″456″这样的字符串。\n[0054] 需要特殊说明一下图3中的虚拟内存(vm)字段,只有打开了Redis的虚拟内存功能,此字段才会真正的分配内存,该功能默认是关闭状态的。通过图3可以发现虽然Redis使用redisObject来表示所有的key/value数据存在内存浪费,但这种内存管理成本的付出主要也是为了给Redis中不同数据类型提供一个统一的管理接口,便于使用者的操作和维护,并且Redis中也进一步提供了多种方法帮助使用者尽量节省内存的使用。\n[0055] 下面对的有序集合结构使用和内部实现方式进行说明。\n[0056] 有序集合(Sorted set)结构\n[0057] 可提供的命令:\n[0058] zrevrank,zrevrange,zadd,exists,zadd,zrange,zrem,zcard等[0059] 使用场景:\n[0060] Redis的sorted set通过用户额外提供的一个优先级(score)参数来为成员排序,并且是插入有序的,即自动排序。当需要一个有序的并且不重复的集合列表时,那么可以选择sorted set数据结构。\n[0061] 实现方式:\n[0062] Redis sorted set的内部使用哈希表(HashMap)和跳跃表(SkipList)来保证数据的存储和有序,HashMap里放的是成员到score的映射,而跳跃表里存放的是所有的成员,排序依据是HashMap里存的score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。\n[0063] 由上所述,本方案采用Redis的sorted set结构,该结构通过使用跳跃表能够具有如下优点:\n[0064] 1:数据在插入时是有序的,能够实现数据的自动排序,无需另行进行数据的排序,降低了数据管理和维护的工作量;\n[0065] 2:能够按照一定数量的条数实现数据的批量查询,支持按范围查询数据,从而提高了数据访问效率;\n[0066] 并且,这种数据结构提供了很多优化内存使用的功能,能够进一步提高索引数据的查询性能。\n[0067] 进一步的,为了节省redis的内存管理成本,本实施例中还提供了一系列的参数和方法来控制和节省内存,具体如下:\n[0068] 1)首先,不要开启Redis的VM选项,即虚拟内存功能。该功能是作为Redis存储超出物理内存数据的一种数据在内存与磁盘换入换出的一个持久化策略,但是其内存管理成本也非常的高,并且此种持久化策略并不成熟,所以要关闭VM功能,将redis.conf文件中的vm-enabled设置为no。\n[0069] 2)其次,设置redis.conf文件中的maxmemory选项。该选项的功能是通知Redis在使用了多少物理内存后就开始拒绝后续的写入请求,该选项能很好的保护好Redis,不会因为使用了过多的物理内存而导致swap,最终严重影响性能甚至崩溃,所以本方案中设置该选项。\n[0070] 3)另外,Redis为不同数据类型分别提供了一组参数来控制内存使用。在前面分析过的Redis Hash在value内部为一个Map结构,如果该Map的成员数比较少,则会采用类似一维线性的紧凑格式来存储该Map,即省去了大量指针的内存开销,这个参数控制对应在redis.conf配置文件中下面2项:\n[0071] hash-max-zipmap-entries 64\n[0072] hash-max-zipmap-value 512\n[0073] 含义是当value的这个Map内部不超过多少个成员时会采用线性紧凑格式存储,默认是64,即value内部有64个以下的成员就使用线性紧凑存储,超过该值自动转成真正的HashMap。\n[0074] hash-max-zipmap-value含义是当value的这个Map内部的每个成员值长度不超过多少字节就会采用线性紧凑存储来节省空间。\n[0075] 以上2个条件的任意一个条件超过设置值时,Map都会转换成真正的HashMap,也就不会再节省内存了。然而该设置值也并非越大越好,HashMap的优势就是查找和操作的时间复杂度都是O(1)的,而放弃HashMap采用一维存储则是O(n)的时间复杂度,如果成员数量很少,则影响不大,否则会严重影响性能,所以要权衡好这个设置值的具体数值,总体上还是最根本的时间成本和空间成本上的权衡。\n[0076] 同样类似的参数还有:\n[0077] list-max-ziplist-entries 512\n[0078] 说明:list数据类型多少节点以下会采用去指针的紧凑存储格式。\n[0079] list-max-ziplist-value 64\n[0080] 说明:list数据类型节点值大小小于多少字节会采用紧凑存储格式。\n[0081] set-max-intset-entries 512\n[0082] 说明:set数据类型内部数据如果全部是数值型,且包括多少节点以下会采用紧凑格式存储。\n[0083] 4)最后,采用共享整型(shared integer)的方式。\n[0084] Redis内部实现没有对内存分配方面做过多的优化,在一定程度上会存在内存碎片,大多数情况下这个不会成为Redis的性能瓶颈,不过如果在Redis内部存储的大部分数据是数值型的话,Redis内部采用了一个shared integer的方式来省去分配内存的开销,即在系统启动时先分配一个从1~n的多个数值对象放在一个数据池中,如果存储的数据恰好是这个数值范围内的数据,则直接从数据池里取出该对象,并且通过引用计数的方式来共享,这样在系统存储了大量数值下,也能一定程度上节省内存并且提高性能。可以通过修改源代码中的宏定义设置上述参数值n,例如,对宏定义REDIS_SHARED_INTEGERS的值进行修改,该值默认是10000,可以根据实际的需要进行修改,修改后重新编译,以达到进一步节省内存的效果。\n[0085] 本发明实施例二提供的获取Feed索引的方法,参见图4,具体包括如下处理:\n[0086] 1:客户端需要获取Feed索引时,向客户端服务器发送查询请求,该查询请求中携带相关参数,如UserID和用于指示查询维度的查询内容指示信息等。\n[0087] 2:客户端服务器对查询请求进行参数检查。\n[0088] 对查询请求中各参数的合法性进行检查,确认查询请求合法时,执行查询操作。\n[0089] 3:客户端服务器同时向索引表缓存和关系型数据库发送查询请求。\n[0090] 客户端服务器按照分片处理机制将查询请求分别发送至相应的索引表缓存和关系型数据库。\n[0091] 4:索引表缓存和关系型数据库分别返回查询结果。\n[0092] 索引表缓存可以通过如下方式查找到Feed索引:\n[0093] 根据查询请求中的用户标识获取到用户的偏移量(offset),所述偏移量指示当前所需获取索引表时的起始位置。如根据用户标识通过zrevrank命令获取到偏移量,该偏移量可以由数据结构中用户数组的下标表示,通过zrevrank命令查找到用户的下标得到该偏移量。\n[0094] 根据查询请求中的查询内容指示信息,在相应的索引表中从所述起始位置开始提取预定条数的Feed索引,作为查询结果。该查询内容指示信息指示查询的维度(dim),如NewsFeed或Timelines。具体的,在获取到偏移量之后,通过zrevrange命令提取预定条数的Feed索引,例如,获取UserId为200034731的用户的Timelines中从FeedId为\n5514194530754113613开始的20条Feed的索引,则查询条件可以表示为:\n[0095] UserId=200034731,\n[0096] offset=551419453075411361,\n[0097] count=20,dim=timelines,\n[0098] key=Indexes:200034731:Timelines。\n[0099] 关系型数据库通过SQL对查询请求进行解析,查询获取Feed索引数据。\n[0100] 5:使用先返回的查询结果。\n[0101] 在本方案中,关系型数据库中存储了系统中所有的Feed索引,而索引表缓存中仅存储了系统中部分的Feed索引,索引表中存储的Feed索引与关系型数据库中的相应Feed索引是一致的,从而保证了无论先返回查询结果的是关系型数据库还是索引表缓存,本方案都能查询到所需的Feed索引。\n[0102] 当索引表缓存和关系型数据库中都存在所查询的Feed索引时,由于索引表缓存仅需要在缓存中查询数据且不需进行SQL解析,速度较快,通常情况下,索引表缓存先返回查询结果。但在一些特殊场景下,也可能是关系型数据库先返回Feed索引。\n[0103] 当索引表缓存中不存在所查询的Feed索引时,先返回查询结果的只能是关系型数据库了。这时,索引表数据库可以不返回查询结果,或者返回消息的内容为空,当出现这种情况时,客户端服务器就能判断出索引表缓存中不包括该Feed索引,将先返回的查询结果中的Feed索引填充至索引表缓存,执行步骤6,否则,该步骤6可以略去。\n[0104] 进一步的,当需要判断索引表缓存中是否存在某Feed索引时,客户端服务器也可以主动向索引表缓存发送查询请求,索引表缓存根据该查询请求利用exists命令查询是否存在相应的Feed索引。\n[0105] 6:将先返回的查询结果中的Feed索引填充至索引表缓存。\n[0106] 本实施例采用批量处理的方法对索引表缓存进行填充,例如,当索引表缓存利用Redis存储系统中的有序集合结构实现时,当客户端服务器发现Redis索引表缓存没有本次查询的索引数据时,则根据关系型数据库返回的查询结果利用Redis的批量(Multipipline)能力将Feed索引批量追加到Redis服务器的缓存中,并按照有序集合的数据结构将该索引数据存储在缓存中。采用这种批量处理的方式,主要考虑到实际中一次查询所获取的Feed索引通常具有多条,批量处理能够快速实现关系型数据库和索引表缓存的一致。\n[0107] 进一步的,本方案中为索引表缓存设置了滑动过期阈值,当一个用户的Feed索引在索引表缓存中的存放时间超过所述滑动过期阈值时,删除该用户在索引表缓存中的Feed索引。该滑动过期阈值的具体数值可以根据需要进行调整,例如,1小时。\n[0108] 索引表缓存在初始化时可以缓存一定条数(如60条)的索引数据,该条数可以根据运维情况或统计计数进行配置调整,在后续的索引查询过程中,会不断有新的索引数据追加到索引表缓存的索引表中,则当一个用户的Feed索引在索引表缓存中的时间超过滑动过期阈值时,如超过1小时后,利用Redis的回收线程进行强制删除,这种处理方式实现了一种简单的最近最少使用(Least Recently Used,LRU)方案,能够控制缓存的容量,节省缓存空间。\n[0109] 考虑到实际场景中,用户主动请求删除Feed索引的需求出现的概率较低,本方案中的索引表缓存可以不设置Feed索引的主动删除功能,以简化索引表缓存的实现,仅利用上述所设置的滑动过期阈值对Feed索引进行强制删除。\n[0110] 7:客户端服务器向非关系型数据库发送请求消息。\n[0111] 本实施例中将系统中所有的Feed内容分别存储至多个非关系型数据库中,即非关系型数据库也采用了一种分片处理的机制。\n[0112] 客户端服务器根据获取到的Feed索引向相应的非关系型数据库发送请求,例如,客户端服务器根据Feed索引中的FeedId,向存储有该FeedId所对应的Feed内容的非关系型数据库发送请求消息,请求获取Feed内容\n[0113] 8:非关系型数据库返回内容。\n[0114] 非关系型数据库(如nosql或mysql+handlersocket)向客户端服务器发送反馈消息,将Feed内容返回至客户端服务器。\n[0115] 由于nosql等非关系型数据库大多基于树结构进行查找,不存在查询语句解析过程,且具有很大的内存缓冲区来提高热点数据的查询,一般不会影响查询的性能,所以本方案在查询Feed内容时仍采用非关系型数据库的方式。\n[0116] 9:客户端服务器生成Feed列表并输出至客户端。\n[0117] 客户端服务器将查询到的Feed索引和Feed内容进行合并生成Feed列表并输出至客户端。\n[0118] 进一步的,本方案中还可以实现对索引表缓存中Feed索引的追加,以满足业务需要。当系统中增加了一个新的用户时,非关系型数据库将新用户的Feed内容写入内容表的Content中,客户端服务器向关系型数据库和索引表缓存发送请求,请求追加索引,则关系型数据库利用SQL命令将新用户的Feed索引插入该数据库的索引表中,索引表缓存利用zadd命令将新用户的Feed索引插入该缓存的索引表中。\n[0119] 当系统中已有的用户生成了新的Feed时,非关系型数据库将该用户新的Feed内容写入内容表的Content中,客户端服务器向关系型数据库和索引表缓存发送请求,请求追加索引,则关系型数据库利用SQL命令将该用户新的Feed索引插入数据库中该用户的索引表中,索引表缓存利用zadd命令将该用户新的Feed索引插入缓存中该用户的索引表中。\n[0120] 由上所述,本方案总体基于如下思路:客户端服务器(如客户端服务器上运行的应用程序)发起获取某个维度的Feed索引查询,同时向索引表缓存和关系型数据库发出异步查询指令,先返回的查询结果会被使用,后返回的在做完必要的处理后会被丢弃。在实现索引表缓存时会利用Redis的高效的Sorted set数据结构,利用FeedId(其由应用程序来生成,生成规则是按时间递增)作为Sorted set的score,通过zrevrank,zrevrange,zadd,exists等命令来实现按照一定范围查询和追加。当需要插入索引时,同时插入关系型数据库和Redis缓存以保证两者的状态一致性。\n[0121] 本发明实施例三还提供了一种获取动态Feed索引的系统,参见图5,所述系统中设置有采用键值对存储结构建立索引表缓存51,所述系统还包括关系型数据库52和客户端服务器53,\n[0122] 所述索引表缓存51中的Feed索引与关系型数据库中的相应Feed索引一致;\n[0123] 所述客户端服务器53向索引表缓存和关系型数据库发送查询请求,并将索引表缓存和关系型数据库中先返回的查询结果作为所获取的Feed索引。\n[0124] 进一步的,本系统中还包括非关系型数据库54,用于存储Feed内容。\n[0125] 上述系统可以采用分片处理机制,系统中包括多个索引表缓存、多个关系型数据库和多个非关系型数据库。客户端服务器可以利用一台服务器实现也可以多个服务器构成的服务器集群实现,客户端服务器上运行的软件可以通过一个独立的类库实现,包括数据库分片、Redis分片、过期策略、缓存数据条数等,该类库可以通过配置实现。\n[0126] 每一索引表缓存51可以利用多个Redis服务器构成的服务器集群实现。客户端服务器根据该查询请求在多个索引表缓存中选取相应的索引表缓存,并在多个关系型数据库中选取相应的关系型数据库,客户端服务器同时向所选取的索引表缓存和所选取的关系型数据库发送查询请求。\n[0127] 在一次查询过程中,若客户端服务器53接收到的先返回的查询结果来自索引表缓存51时,则客户端服务器在接收到关系型数据库52返回的查询结果时,丢弃该查询结果;\n[0128] 在一次查询过程中,若客户端服务器53接收到的先返回的查询结果来自关系型数据库52时,则当客户端服务器接收到索引表缓存51返回的查询结果时,丢弃该查询结果,当客户端服务器没有接收到索引表缓存51返回的查询结果例如,在预置的响应时间内未接收到索引表缓存返回的查询结果或者对先返回的查询结果处理完成以后仍未接收到索引表缓存返回的查询结果,客户端服务器获知索引表缓存中未存储相应的Feed索引,或者,当客户端服务器接收到索引表缓存返回的内容为空的消息时,客户端服务器也能获知到索引表缓存中未存储相应的Feed索引,这时,采用批量填充的方式将查询结果中的Feed索引填充至索引表缓存51。\n[0129] 上述索引表缓存采用的键值对存储结构为Redis存储系统中的有序集合结构,所述有序集合结构的哈希表中存放用户至优先级的映射,该优先级设置为用户的动态标识FeedId,所述有序集合结构的跳跃表中存放根据所述优先级排序后的所有用户。\n[0130] 进一步的,上述索引表缓存利用如下方式得到查询结果:\n[0131] 上述查询请求中包括用户标识和查询内容指示信息;根据查询请求中的用户标识获取到用户的偏移量,所述偏移量指示当前所需获取索引表时的起始位置;根据查询请求中的查询内容指示信息,在相应的索引表中从所述起始位置开始提取预定条数的Feed索引,作为查询结果。例如,索引表缓存根据用户标识通过zrevrank命令获取到所述偏移量;\n以及,索引表缓存根据查询内容指示信息通过zrevrange命令在相应的索引表中从所述起始位置开始提取预定条数的Feed索引,作为查询结果。\n[0132] 进一步的,在索引表缓存中设置有滑动过期阈值,当一个用户的Feed索引在索引表缓存中的存放时间超过所述滑动过期阈值时,删除该用户在索引表缓存中的Feed索引。\n并且,索引表缓存和关系型数据库能够追加一个新用户的Feed索引或已有用户的新Feed索引,非关系型数据库能够追加一个新用户的Feed内容或已有用户的新Feed内容。\n[0133] 由上所述,本发明实施例提供了一种新型的并行查询机制,同时使用所设置的索引表缓存和关系型数据库查询数据,使用先返回的查询结果,不但保证了查询的快速响应,也避免了对关系型数据库的依赖,无需在每次查询时进行SQL解析,从而保证了在高并发查询和索引表的数据量较大的场景下也能得到较佳的查询性能。\n[0134] 进一步的,本发明实施例通过缓存操作减少了磁盘的I/O操作,降低了数据访问的压力,以尽可能降低Feed索引的查询业务对系统中其他业务的影响,保证了系统整体性能的稳定。\n[0135] 本发明实施例的技术方案至少具有如下优点:\n[0136] 1)基于Redis的有序集合结构来实现索引表缓存,能够带来明显的查询性能提升;\n[0137] 2)通过缓存操作减少了磁盘的I/O,降低了数据访问的压力,从而可以使系统更好地为其他业务服务,是一种以空间换时间的方案;\n[0138] 3)在实现时很多命令基于Redis的Multipipeline模式,从而减少了与Redis服务器的交互,利用Redis的有序集合结构实现了自动倒序,降低了由客户端排序的复杂性;\n[0139] 4)客户端支持并行使用Redis和关系型数据库来查询索引数据,保证了快速响应;\n[0140] 5)客户端服务器上运行的软件可以通过一个独立的类库实现,从而可以根据业务量等进行调整,实现了低耦合处理。\n[0141] 以上所述仅为本发明的较佳实施例而已,并非用于限定本发明的保护范围。凡在本发明的精神和原则之内所作的任何修改、等同替换、改进等,均包括在本发明的保护范围内。
法律信息
- 2020-09-15
专利权人的姓名或者名称、地址的变更
专利权人由北京新媒传信科技有限公司变更为北京新媒传信科技有限公司
地址由100089 北京市海淀区万泉庄路28号万柳新贵大厦A座6层602室变更为100080 北京市海淀区海淀大街34号8层810室
- 2016-02-17
- 2013-07-24
实质审查的生效
IPC(主分类): G06F 17/30
专利申请号: 201110439565.6
申请日: 2011.12.23
- 2013-06-26
引用专利(该专利引用了哪些专利)
序号 | 公开(公告)号 | 公开(公告)日 | 申请日 | 专利名称 | 申请人 |
1
| |
2010-12-29
|
2010-09-09
| | |
2
| |
2011-04-13
|
2010-11-10
| | |
3
| |
2011-07-27
|
2011-04-22
| | |
4
| |
2007-12-19
|
2007-05-25
| | |
被引用专利(该专利被哪些专利引用)
序号 | 公开(公告)号 | 公开(公告)日 | 申请日 | 专利名称 | 申请人 | 该专利没有被任何外部专利所引用! |