QQ邮箱密码忘记了,京东忘记密码怎么找回回?

redis 怎么做条件查询? - 知乎23被浏览10368分享邀请回答21 条评论分享收藏感谢收起1添加评论分享收藏感谢收起更多RediSearch-Redis强大的搜索引擎
作者/翻译:张冬洪,Redis中国用户组主席
RediSearch简介
RediSearch是一个高性能的全文搜索引擎,可作为一个Redis Module 运行在Redis上,是由RedisLabs团队开发的。
特点是:Faster, in-memory, highly available full text search
项目地址:/RedisLabsModules/RediSearch
官网:http://redisearch.io
RediSearch 是在Redis基础上从0开始开发的一个全文搜索索引,使用新的Redis Modules API来扩展Redis新命令和能力,它的主要特性包括:
简单,快速索引和搜索
数据存储在内存中,使用内存-有效的自定义数据结构
支持多种使用UTF-8编码的语言
文档和字段评分
结果的数值过滤
通过词干扩展查询
精确的短语搜索
按特定属性过滤结果(例如仅在标题中搜索“foo”)
强大的自动提示引擎
增量索引(不需要对索引进行优化和压缩)
支持用作存储在另一数据库中的文档的搜索索引
支持已经在Redis中存在的HASH对象作为文件的索引
扩展到多个Redis实例
RediSearch实战 - 小试牛刀
通过下面的案例让我们一起来了解一下关于RediSearch的一些关键概念,下面的例子是在redis-cli 工具基础上完成的。
1. 定义一个索引
为了搜索的有效性,RediSearch需要知道怎样去索引文档。一个文档可以有若干字段,每一个都有它们自己的权重(例如:标题通常比文本本身更重要)。搜索引擎能够使用数值字段来进行过滤(未来我们将会增加更多的字段)。
因此,第一步是创建索引定义,它告诉RediSearch如何处理我们将会添加的文档。
在这个案例中,我们将创建一个产品目录索引,其中每个产品都有名称,描述和价格(允许我们通过价格过滤产品)。
我们使用 FT.CREATE 命令,它的语法是:
在本例中:
这就意味着产品名称和描述被视为文本字段,其各自的得分是10分和1分,这个价格是用于过滤的数值字段。
2. 添加文档
现在我们可以使用 FT.ADD 命令添加一个新的文档到我们的索引:
添加一个TV作为例子:
该产品被立即添加索引中,现在可以在未来的搜索中被找到。
注:RediSearch支持UTF-8(或纯ASCII)编码的文本,不检查输入的有效性,其主要的限制是使用普通的空格和标点符号标记标志,它对ASCII和UTF-8都起作用。
现在我们已经有了被添加到索引中的产品,用 FT.SEARCH 命令进行搜索是非常简单的:
或者用价格过滤,如价格在$200到$300之间:
在redis-cli 客户端上输出的结果信息如下:
现在我们已经论证了RediSearch是如何工作的,我们将在短时间内热切的投入到RediSearch的开发和设计中。
为了评估RediSearch相比其他开源搜索引擎的性能,我们创建了一套度量延迟和吞吐量的基准—索引和查询相同的数据集。我们的基准测试结果表明RediSearch的速度相比ElasticSearch 和 Solr要快120%到500%。
基准设置:
数据集:从维基百科页面提供的有用的英文摘要的转储,其中包括510万短摘要。
基准测试:我们针对不同的搜索引擎运行了几个具有不同配置文件的查询。并行的运行1, 8, 16、32和64个并发客户端执行每个查询。我们也跑了自动完成测试,从具有相同客户端并发配置文件的数据集中测试前1100名最受欢迎的2和3个字母前缀。
物理配置:2个 c4.4x large AWS EC2 Instance,每一个配置16核,32GB内存 和 SSD EBS 存储,一个用作client,另一个运行 servers
搜索引擎测试:
RediSearch:5个分片运行在5个Redis Masters上,没有负载均衡,冗余或内置的缓存,此设置最多使用了Server机器的5个CPU核心。
ElasticSearch:一个实例有5个分片,过滤器缓存已禁用,在基准测试中,ElasticSearch使用了所有的16个CPU核心,因为它是多线程的。
Solr:solr-cloud的两个实例,每一个实例上面运行2个分片,缓存是完全禁用的,在基准测试过程中,Solr也是使用了所有的16个CPU核心。
客户端:使用GO编写的应用程序,利用尽可能多的CPU核心,对于Redis, ElasticSearch 和 Solr 都使用流行的GO客户端压测,测试程序地址:/RedisLabs/RediSearchBenchmark
压测结果展示:
我们已经证明,利用Redis Module API,我们可以在Redis的上面创建一个功能丰富和高性能的搜索引擎。
从基准测试来看,使用RediSearch 要优于其他搜索引擎,在某些情况下还有很大的盈余 - 保持较低的延迟。
然而相比于ElasticSearch和Solr,RediSearch仍然需要获得更多的特性,其性能优势使得它可以成为许多用例的可行替代品,并且随着时间的推移,我们打算在开源社区的帮助下对它进行加强。
写在最后,原文翻译自:http://redisearch.io/ 以及《RediSearch白皮书》
责任编辑:
声明:本文由入驻搜狐号的作者撰写,除搜狐官方账号外,观点仅代表作者本人,不代表搜狐立场。告诉你Redis是一个牛逼货 - 简书
告诉你Redis是一个牛逼货
Redis 是一个 Key-Value 存储系统。和 Memcached 类似,它支持存储的 value 类型相对更多,包括 string(字符串)、 list(链表)、 set(集合)和 zset(有序集合)。这些数据类型都支持 push/pop、add/remove 及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,Redis 支持各种不同方式的排序。与 memcached 一样,为了保证效率,数据都是缓存在内存中。区别的是 Redis 会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了 master-slave(主从)同步。
Key-Value存储系统
Key-Value Store 是当下比较流行的话题,尤其在构建诸如搜索引擎、IM、P2P、游戏服务器、SNS 等大型互联网应用以及提供云计算服务的时候,怎样保证系统在海量数据环境下的高性能、高可靠性、高扩展性、高可用性、低成本成为所有系统架构们挖苦心思考虑的重点,而怎样解决数据库服务器的性能瓶颈是最大的挑战。Key-Value Store 更加注重对海量数据存取的性能、分布式、扩展性支持上,并不需要传统关系数据库的一些特征,例如:Schema、事务、完整 SQL 查询支持等等,因此在分布式环境下的性能相对于传统的关系数据库有较大的提升。
为什么要选择Key-Value Store
大规模互联网应用一类是仍然采用RDBMS,然后通过对数据库的垂直和水平切分将整个数据库部署到一个集群上,缺点在于它是针对特定应用,通用型不足另一类就是google采用的方法,抛弃RDBMS,采用Key-Value形式存储,这样可以极大增强系统的可扩展性。
云存储如果说上一个问题还有可以替代的解决方案(切割数据库)的话,那么对于云存储来说,也许 key-value 的 store 就是唯一的解决方案了。云存储简单点说就是构建一个大型的存储平台给别人用,这也就意味着在这上面运行的应用其实是不可控的。如果其中某个客户的应用随着用户的增长而不断增长时,云存储供应商是没有办法通过数据库的切割来达到 scale 的,因为这个数据是客户的,供应商不了解这个数据自然就没法作出切割。在这种情况下,key-value 的 store 就是唯一的选择了,因为这种条件下的 scalability 必须是自动完成的,不能有人工干预。这也是为什么几乎所有的现有的云存储都是 key-value 形式的,例如 Amazon的 smipleDB,底层实现就是 key-value,还有 google 的
GoogleAppEngine,采用的是 BigTable的存储形式。
Key-Value Store 最大的特点就是它的可扩展性,这也就是它最大的优势。所谓的可扩展性,在我看来这里包括了两方面内容。一方面,是指 Key-Value Store 可以支持极大的数据的存储,它的分布式的架构决定了只要有更多的机器,就能够保证存储更多的数据。另一方面,是指它可以支持数量很多的并发的查询。对于 RDBMS,一般几百个并发的查询就可以让它很吃力了,而一个 Key-Value Store,可以很轻松的支持上千的并发查询。下面而简单的罗列了一些特点:?
Key-value store:一个
数据存储系统,只支持一些基本操作,如: SET(key, value) 和
分布式:多台机器(nodes)同时存储数据和状态,彼此交换消息来保持数据一致,可视为一个完整的存储系统。?
数据一致:所有机器上的数据都是同步更新的、不用担心得到不一致的结果;?
冗余:所有机器(nodes)保存相同的数据,整个系统的存储能力取决于单台机器(node)的能力;?
容错:如果有少数
出错,比如重启、当机、断网、网络丢包等各种
fault/fail
都不影响整个系统的运行;?
高可靠性:容错、冗余等保证了数据库系统的可靠性。
Redis是一个开源的使用ANSI C语言编写,支持网络、可基于内存且可持久化的日志型、Key-Value数据库,并且提供多个语言的API,访问十分便捷。
Redis数据类型:
作为 Key-value 型数据库,Redis 也提供了键(Key)和键值(Value)的映射关系。但是,除了常规的数值或字符串,Redis 的键值还可以是以下形式之一:?
Sorted sets
(有序集合)?
(哈希表)键值的数据类型决定了该键值支持的操作。Redis 支持诸如列表、集合或有序集合的交集、并集、查集等高级原子操作;同时,如果键值的类型是普通数字,Redis 则提供自增等原子操作。
Redis持久化:
通常,Redis 将数据存储于内存中,或被配置为使用虚拟内存。通过两种方式可以实现数据持久化:使用截图的方式,将内存中的数据不断写入磁盘;或使用类似 MySQL 的日志方式,记录每次更新的日志。前者性能较高,但是可能会引起一定程度的数据丢失;后者相反。
Redis主从同步:
Redis支持将数据同步到多台从库,这种特性对提高读取性能非常有益
Redis性能:
相比需要依赖磁盘记录每个更新的数据库,基于内存的特性无疑给Redis带来了非常优秀的性能,读写操作之间有显著的性能差异性能测试结果:
SET操作每秒钟 110000 次,GET操作每秒钟 81000 次,服务器配置如下:Linux 2.6, Xeon XGhz.stackoverflow 网站使用 Redis 做为缓存服务器。
适用场合:
Redis其实开创了一种新的数据存储思路,使用Redis,我们不用再面对功能单调的数据库时,把精力放在如何把大象放进冰箱的问题,而是利用Redis提供的灵活多变的数据结构和数据操作,为不同的大象构建不同的冰箱。
下面是一些Redis常用的场景:
1. 取最新N个数据的操作
比如典型的取你网站的最新文章,通过下面方式,我们可以将最新的 5000 条评论的 ID 放在Redis 的 List 集合中,并将超出集合部分从数据库获取。使用 ments&ID&命令,向 list 集合中插入数据插入完成后再用 ments 0 5000 命令使其永远只保存最近 5000 个 ID如果你还有不同的筛选维度,比如某个分类的最新 N 条,那么你可以再建一个按此分类的List,只存 ID 的话,Redis 是非常高效的。
2. 排行榜应用,取TOP N操作
这个需求与上面需求的不同之处在于,前面操作以时间为权重,这个是以某一个条件为权重,比如按购买的次数或者顶的次数,这时候就需要 sorted set 出马,将你要排序的值设置为sorted set的score,将具体的数据设置为相应的value,每次只需要执行一条ZADD命令即可。
3. 需要精确设定过期时间的应用
比如你可以把上面说到的 sorted
set 的 score 值设置成过期时间的时间戳,那么就可以简单地通过过期时间排序,定时清除过期数据了,不仅是清除 Redis 中的过期数据,你完全可以把 Redis 里这个过期时间当成是对数据库中数据的索引,用 Redis 来找出哪些数据需要过期删除,然后再精准地从数据库中删除相应的记录。
4.计数器应用Redis的命令是原子性的,你可以轻松利用INCR、DECR命令来构建计数器系统(底层的写入是单线程模型,并发写会按到位顺序执行)
5.Uniq操作,获取某段时间所有数据去重值
这个使用Redis的Set数据结构最合适,只需要不断将数据往Set中扔就行,set就是集合,会自动去重
6.实时系统、发垃圾系统
通过上面说到的 set 功能,你可以知道一个终端用户是否进行了某个操作,可以找到其操作的集合并进行分析统计对比等。没有做不到,只有想不到。
7.Pub、Sub构建实时消息系统
Redis 的 Pub/Sub 系统可以构建实时的消息系统,比如很多用 Pub/Sub 构建的实时聊天系统的例子。
8. 构建队列系统
使用list可以构建队列系统,使用sorted set 甚至可以构建有优先级的队列系统。
性能优于Memcached,并且更优秀的在于数据结构更加多样化
Redis作者的宣言
宣言中,作者列举了Redis的7大原则,可以向大家阐明Redis的思想,看了之后我觉得Redis的作者的确牛叉,Redis这款产品这的是程序猿的福利:1. Redis 是一个操作数据结构的语言工具,它提供基于 TCP 的协议以操作丰富的数据结构。在 Redis 中,数据结构这个词的意义不仅表示在某种数据结构上的操作,更包括了结构本身及这些操作的时间空间复杂度。2. Redis 定位于一个内存数据库,正是由于内存的快速访问特性,才使得 Redis 能够有如此高的性能,才使得 Redis 能够轻松处理大量复杂的数据结构,Redis 会尝试其它的存储方面的选择,但是永远不会改变它是一个内存数据库的角色。3.
Redis 使用基础的 API 操作基础的数据结构, Redis 的 API 与数据结构一样,都是一些最基础的元素,你几乎可以将任何信息交互使用此 API 格式表示。作者调侃说,如果有其它非人类的智能生物存在,他们也能理解 Redis 的 API。因为它是如此的基础。(作者大大很有趣)4. Redis 有着诗一般优美的代码,经常有一些不太了解 Redis
有的人会建议 Redis 采用一些其它人的代码,以实现一些 Redis
未实现的功能,但这对我们来说就像是非要给《红楼梦》接上后四十回一样。5.Redis 始终避免复杂化,我们认为设计一个系统的本质,就是与复杂化作战。我们不会为了一个小功能而往源码里添加上千行代码,解决复杂问题的方法就是让复杂问题永远不要提复杂的问题。6.Redis 支持两个层成的 API,第一个层面包含部分操作 API,但它支持用于分布式环境下的 Redis。第二个层面的 API 支持更复杂的 multi-key 操作。它们各有所长,但是我们不会推出两者都支持的 API,但我们希望能够提供实例间数据迁移的命令,并执行 multi-key 操作。7. 我们以优化代码为乐,我们相信编码是一件辛苦的工作,唯一对得起这辛苦的就是去享受它。如果我们在编码中失去了乐趣,那最好的解决办法就是停下来。我们决不会选择让Redis不好玩的开发模式。
我只能感叹道:Redis乃神物,出污泥而不染,濯清涟而不妖。
PS: Redis作者antirez曾笑称Redis为一个数据结构服务器,我认为这个还是挺准确的,Redis的所有功能就是将数据以其固有的几种结构来保存,并提供给用户操作这几种结构的接口。
redis:redis中文:问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
问题如题,注意不是指模糊查询Key,是指对值的模糊(关键字)查询。举个栗子:
$ HMSET user:1 name jack age 18
$ HMSET user:2 name jackson age 21
$ HMSET user:3 name suse age 16
假如有上述用户数据,以哈希形式存储,如果要做排序,可以
# score为#age,value为#userId,以ZSET结构存储
$ ZADD user:rank:age 18 1 21 2 16 3
# 查询有序列表
$ ZRANGE user:rank:age 0 -1
但如果需要既实现根据年龄排序,还要能够实现关键字查询(模糊匹配用户名),应该怎样实现?
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
有一种变通的方法,一定程度上可以实现简单、小数据量的模糊查询:写入用户信息时,将用户名分拆作为Key,来记录用户ID
SADD user:like:j jack jackson
SADD user:like:ja jack jackson
SADD user:like:jac jack jackson
SADD user:like:jack jack jackson
SADD user:like:jacks jackson
SADD user:like:jackso jackson
SADD user:like:jackson jackson
后面模糊查询时,输入:j,则可以从SET集合中查出jack、jackson两项,当然,这两项值可以用用户ID来代替,再根据用户ID来查询用户哈希信息。此方式仅适用于查询条件单一、且字段长度较短场景,如果:同时模糊匹配帖子标题和帖子文章,就不行了,标题还能试试,内容肯定无法实现的。
当然Redis先天不适合做这件事,所以有别的方案,还是建议用别的方案来实现。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
委婉的方式是自己写lua脚本。或者数据集不大的情况下自己在客户端过滤。如果模糊查询是硬需求,建议转移到solr或elasticsearch来做。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
Redis 没有那么丰富的查询方法, 模糊查询也只能在 key 中进行,并不能满足你这么丰富的需求。如果要高速存储建议使用 Redis, 如果是想进行业务逻辑,要有丰富的查询方式,建议使用MongoDb
同步到新浪微博
分享到微博?
Hi,欢迎来到 SegmentFault 技术社区!⊙▽⊙ 在这里,你可以提出编程相关的疑惑,关注感兴趣的问题,对认可的回答投赞同票;大家会帮你解决编程的问题,和你探讨技术更新,为你的回答投上赞同票。
明天提醒我
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:
扫扫下载 App来源:jasonGeng88
</jasonGeng88/blog/blob/master/201706/redis-search.md
如有好文章投稿,请点击 → 这里了解详情
大家如果是做后端开发的,想必都实现过列表查询的接口,当然有的查询条件很简单,一条 SQL 就搞定了,但有的查询条件极其复杂,再加上库表中设计的各种不合理,导致查询接口特别难写,然后加班什么的就不用说了(不知各位有没有这种感受呢~)。
下面以一个例子开始,这是某购物网站的搜索条件,如果让你实现这样的一个搜索接口,你会如何实现?(当然你说借助搜索引擎,像 Elasticsearch 之类的,你完全可以实现。但我这里想说的是,如果要你自己实现呢?)
从上图中可以看出,搜索总共分为6大类,每大类中又分了各个子类。这中间,各大类条件之间是取的交集,各子类中有单选、多选、以及自定义的情况,最终输出符合条件的结果集。
好了,既然需求很明确了,我们就开始来实现。
率先登场是小A同学,他是写 SQL 方面的“专家”。小A信心满满的说:“不就是一个查询接口吗?看着条件很多,但凭着我丰富的 SQL 经验,这点还是难不倒我的。”
于是乎就写出了下面这段代码(这里以 MYSQL 为例):
select...from table_1
left join table_2
left join table_3
left join(select...from table_x&where...)tmp_1
order&by...
代码在测试环境跑了一把,结果好像都匹配上了,于是准备上预发。这一上预发,问题就开始暴露出来。预发为了尽可能的逼真线上环境,所以数据量自然而然要比测试大的多。所以这么一个复杂的 SQL,它的执行效率可想而知。测试同学果断把小A的代码给打了回来。
总结了小A失败的教训,小B开始对SQL进行了优化,先是通过了explain关键字进行SQL性能分析,对该加索引的地方都加上了索引。同时将一条复杂SQL拆分成了多条SQL,计算结果在程序内存中进行计算。
伪代码如下:
$result_1=&query('select ... from table_1 where ...');
$result_2=&query('select ... from table_2 where ...');
$result_3=&query('select ... from table_3 where ...');
$result=&array_intersect($result_1,$result_2,$result_3,...);
这种方案从性能上明显比第一种要好很多,可是在功能验收的时候,产品经理还是觉得查询速度不够快。小B自己也知道,每次查询都会向数据库查询多次,而且有些历史原因,部分条件是做不到单表查询的,所以查询等待的时间是避免不了的。
小C从上面的方案中看到了优化的空间。他发现小B在思路上是没问题的,将复杂条件拆分,计算各个子维度的结果集,最后将所有的子结果集进行一个汇总合并,得到最终想要的结果。
于是他突发奇想,能否事先将各个子维度的结果集给缓存起来,这要查询的时候直接去取想要的子集,而不用每次去查库计算。
这里小C采用 Redis 来存储缓存数据,用它的主要原因是,它提供了多种数据结构,并且在 Redis 中进行集合的交并集操作是一件很容易的事情。
具体方案,如图所示:
这里每个条件都事先将计算好的结果集ID存入对应的key中,选用的数据结构是集合(Set)。查询操作包括:
子类单选:直接根据条件 key,获取对应结果集;
子类多选:根据多个条件 Key,进行并集操作,获取对应结果集;
最终结果:将获取的所有子类结果集进行交集操作,得到最终结果;
这其实就是所谓的反向索引。
这里会发现,漏了一个价格的条件。从需求中可知,价格条件是个区间,并且是无穷举的。所以上述的这种穷举条件的 Key-Value 方式是做不到的。这里我们采用 Redis 的另一种数据结构进行实现,有序集合(Sorted Set):
将所有商品加入 Key 为价格的有序集合中,值为商品ID,每个值对应的分数为商品价格的数值。这样在 Redis 的有序集合中就可以通过ZRANGEBYSCORE命令,根据分数(价格)区间,获取相应结果集。
至此,方案三的优化已全部结束,将数据的查询与计算通过缓存的手段,进行了分离。在每次查找时,只需要简单的查找 Redis 几次就能得出结果。查询速度上符合了验收的要求。
这里你或许发现了一个严重的功能缺陷,列表查询怎么能没有分页。是的,我们马上来看 Redis 是如何实现分页的。
分页主要涉及排序,这里简单起见,就以创建时间为例。
如图所示:
图中蓝色部分是以创建时间为分值的商品有序集合,蓝色下方的结果集即为条件计算而得的结果,通过ZINTERSTORE命令,赋结果集权重为0,商品时间结果为1,取交集而得的结果集赋予创建时间分值的新有序集合。对新结果集的操作即能得到分页所需的各个数据:
页面总数为:ZCOUNT命令
当前页内容:ZRANGE命令
若以倒序排列:ZREVRANGE命令
关于索引数据更新的问题,有两种方式来进行。一种是通过商品数据的修改,来即时触发更新操作,一种是通过定时脚本来进行批量更新。这里要注意的是,关于索引内容的更新,如果暴力的删除 Key,再重新设置 Key。因为 Redis 中两个操作不会是原子性进行的,所以中间可能存在空白间隙,建议采用仅移除集合中失效元素,添加新元素的方式进行。
Redis 是内存级操作,所以单次的查询会很快。但是如果我们的实现中会进行多次的 Redis 操作,Redis 的多次连接时间可能是不必要时间消耗。通过使用MULTI命令,开启一个事务,将 Redis 的多次操作放在一个事务中,最后通过EXEC来进行原子性执行(注意:这里所谓的事务,只是将多个操作在一次连接中执行,如果执行过程中遇到失败,是不会回滚的)。
这里只是一个采用 Redis 优化查询搜索的一个简单 Demo,和现有的开源搜索引擎相比,它更轻量,学习成本也相应低些。其次,它的一些思想与开源搜索引擎是类似的,如果再加上词语解析,也可以实现类似全文检索的功能。
看完本文有收获?请转发分享给更多人
关注「数据库开发」,提升 DB 技能
声明:本文由入驻搜狐号的作者撰写,除搜狐官方账号外,观点仅代表作者本人,不代表搜狐立场。
阅读(...) 评论()}

我要回帖

更多关于 微信忘记密码怎么找回 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信