
一、获取所有Key
[python] view plain copy
# -- encoding: UTF-8 --
__author__ = "Sky"
import redis
pool=redisConnectionPool(host='127001',port=6379,db=0)
r = redisStrictRedis(connection_pool=pool)
keys = rkeys()
print type(keys)
print keys
运行结果:
<type 'list'>
['fad', '1', '2']
二、获取所有内容
[python] view plain copy
import redis
pool = redisConnectionPool(host='127001', port=6379, db=0)
r = redisRedis(connection_pool=pool)
pipe = rpipeline()
pipe_size = 100000
len = 0
key_list = []
print rpipeline()
keys = rkeys()
for key in keys:
key_listappend(key)
pipeget(key)
if len < pipe_size:
len += 1
else:
for (k, v) in zip(key_list, pipeexecute()):
print k, v
len = 0
key_list = []
for (k, v) in zip(key_list, pipeexecute()):
print k, v
运行结果:
fad fda
1 e
Redis是建立在TCP协议上的CS架构,客户端client对redis server采取请求响应的方式交互每次交互会有网络延迟,大约30ms
假设有这样一个场景,redis中存储上千个key值,获取每个key对应field的value,那么要向redis请求上千次 hget(key, field),获取响应也是对应的次数如果能一次性将所有请求提交给server端,执行完成后批量获取响应,只需向redis请求1次,性能获大幅提升
没有用pipeline之前,基本上获取所有数据需要90多s,现在只需03s,性能提升清晰可见
实现以下场景:定时任务每隔1s执行任务函数,但是任务函数执行完成的时间比1s要长,此时启动定时任务要加上两个参数,否则会报错
可允许的实例个数,如果没有设置,则默认为1,表示id相同的任务实例数
像上面的例子中,会报skipped: maximum number of running instances reached (1)的错误,意思APScheduler试图重新执行作业,但前一个仍在运行。
这个参数可以理解为任务的超时容错配置,给executor 一个超时时间,这个时间范围内要是该跑的还没跑完,就别再跑了
像上面的例子中,会报Run time of job …… next run at: ……)” was missed by的错误
通过改变程序搜索数据的方式,并使用 Redis 来减少绝大部分基于单词或者关键字进行的内容搜索 *** 作的执行时间。 P154
倒排索引 (inverted indexes) 是互联网上绝大部分搜索引擎使用的底层结构,它类似于书本末尾的索引。倒排索引从每个被索引的文档里面提取一些单词,并记录包含每个单词的文档集合。 P154
示例
假设有三个文档:
我们就能得到下面的倒排索引集合:
检索的条件 "what", "is" 和 "it" 将对应这个集合: {0,1} ∩ {0,1,2} ∩ {0,1,2} = {0,1}
可以发现 Redis 的集合和有序集合非常适合处理倒排索引。
基本索引 *** 作
从文档里面提取单词的过程通常被成为语法分析 (parsing) 和标记化 (tokenization) ,这个过程可以产生一系列用于表示文档的标记 (token) ,有时又被成为单词 (word) 。 P155
标记化的一个常见的附加步骤就是移除非用词 (stop word) 。非用词就是那些在文档中频繁出现却没有提供相应信息量的单词,对这些单词进行搜索将返回大量无用的结果。 P155
本书中实现方向索引的逻辑非常简单:
如果需要支持中文等,就不能简单进行英文分词,需要分词器进行处理。第一次接触倒排索引是在 Elasticsearch 中,感兴趣的可以了解 Elasticsearch 中倒排索引的实现以及 IK 中文分词器。
基本搜索 *** 作
在索引里面查找一个单词是非常容易的,只需要获取单词集合里面的所有文档即可。根据多个单词查找文档时,就需要根据条件处理对应的集合,再从最终集合中获取所有文档。 P156
可以使用 Redis 的集合 *** 作完成对不同条件的处理:
通过以上三类命令,我们基本能实现条件大部分的与或非 *** 作。
分析并执行搜索
我们使用的查询语句进行分词后具有以下特征:
即: "connect +connection chat -proxy -proxies" 表示查询的文档需要包含 "connect" 或 "connection" ,同时也要包含 "chat" ,并且不能包含 "proxy" 和 "proxies" 。
实际处理时,先对同义词组分别取并集,然后与需要查询的单词一起取交集,最后与不希望包含的单词取差集,这样所得到的集合就是用户查询的结果集。
上述搜索功能以及能够搜索出用户查询的所有文档唯一标识的集合,现在我们将根据这个文档唯一标识集合以及每个文档的具体信息进行排序分页。
对于这种情况我们可以使用 Redis 的 SORT 命令对文档唯一标识集合通过引用每个文档的具体信息进行排序分页。 ( 05 Redis 其他命令简介 )
上面介绍了使用 Redis 进行搜索,并通过引用存储在 HASH 里面的数据对搜索结果进行排序分页。接下来将介绍利用集合和有序集合实现基于多个分值的复合排序 *** 作,它能提供比 SORT 命令更高的灵活性。 P162
假设我们目前需要根据文档对更新时间和得票数进行排序,为此我们需要用两个有序集合存储相关信息。这两个有序集合的成员都是文档唯一标识,成员的分值则分别是文档的更新时间和得票数。
设经过搜索后满足搜索条件的文档唯一标识集合为 filtered_doc_ids ,文档唯一标识及其更新时间对应的有序集合为 doc_ids_with_update ,文档唯一 标识及其得票数对应的有序集合为 doc_ids_with_votes 。那么可以通过 ZINTERSTORE 命令对这三个集合求交集,最后得出的满足搜索条件的文档唯一标识及其排序分值对应的有序集合,再使用 ZRANGE , ZREVRANGE 进行分页获取即可。 P162
示例: ZINTERSTORE filtered_doc_ids_with_sort_score 3 filtered_doc_ids doc_ids_with_update doc_ids_with_votes WEIGHTS 0 {update_weight} {vote_weight}
其中:
所思
这种利用分值的方法很巧妙,基本可以实现多字段排序,但是优先级可能难以掌控,难以做到先按照某一字段排序,再按照另一字段排序的形式。因为每个字段对应的分值的数量级可能差别比较小,这个时候如果需要有排序字段的优先级,那么可能需要对每个权重进行精巧地设计才行。
上面介绍了使用有序集合对多个数值字段进行排序,由于有序集合的分值只能是浮点数,所以非数值字段不能直接用于排序,需要转换成对应的浮点数。但由于双精度浮点数只有 64 个二进制位,实际能使用 63 个二进制位,所以能表示的字符串并不多,只能使用字符串的前几个字符进行分值估计,不足指定字符数的需要补齐到指定字符数。当然如果字符集缩小的话,可以重新进行编码计算,进而可以对更长的字符串进行分值估计。 P165
当这个分值特别大的时候,可能会引发最终计算的分值溢出而出错的问题。
接下来将介绍使用集合和有序集合构建出一个几乎完整的广告服务平台 (ad-serving platform) 。 P166
针对广告的索引 *** 作和针对其他内容的索引 *** 作并没有太大的不同,被索引的的广告通常都拥有像位置、年龄和性别这类必需的定向参数,并且往往只会返回单个广告。 P167
广告的价格 P167
为了尽可能简化广告价格的计算方式,将对所有类型的广告进行转换,使得它们的价格可以基于每千次展示进行计算,产生出一个估算 CPM (estimated CPM, eCPM) 。 P168
将广告插入倒排索引 P169
我们基本可以复用上面提到的搜索功能,除了会将广告的关键词插入倒排索引,还会将广告的定向参数(位置、年龄和性别等)插入倒排索引中,并记录广告的类型、基本价格和 eCPM 价格。 P169
当系统收到广告定向请求的时候,它要做的就是在匹配用户定向参数的一系列广告里面,找出 eCPM 最高的那一个广告。同时,程序还会记录页面内容与广告内容的匹配程度,以及不同匹配程度对广告点击通过率的影响等统计数据。通过使用这些统计数据,广告中与页面相匹配的那些内容就会作为附加值被计入 CPC 和 CPA 的 eCPM 价格,使得那些包含了匹配内容的广告能够更多地被展示出来。 P170
计算附加值
计算附加值就是基于页面内容和广告内容两者之间匹配的单词,计算出应该给广告的 eCPM 价格加上多少增量。每个单词都有一个有序集合,成员为广告 id ,成员的分值为当前单词对这则广告的 eCPM 的附加值。 P171
在寻找合适的广告时,我们首先会过滤出匹配定位位置且至少包含一个页面单词的广告,然后通过计算附加值的方法替代搜索,以便实现每次投放价值最高的广告,并能够根据用户的行为学习。同时由于每个广告匹配的内容不同,最优方式应该是使用加权平均值来计算单词部分的附加值,但限于 Redis 本身的命令,我们最终采取 (max + min) / 2 的形式计算单词部分的附加值(max 表示所有匹配单词的最大附加值, min 表示所有匹配单词的最小附加值),采用如下命令即可: ZUNIONSTORE final_score 3 base max min WEIGHTS 1 05 05 。
从用户行为中学习 P175
首先需要存储用户的浏览记录,包括三部分:(每 100 次就主动更新一次 eCPM ) P175
其次需要存储用户的点击和动作记录,用于计算 点击通过率 = 点击量或动作次数 / 广告展示次数。(每次都更新 eCPM) P176
最后就是更新 eCPM ,包括两部分:
接下来将使用集合和有序集合实现职位搜索功能,并根据求职者拥有技能来为他们寻找合适的职位。 P180
第一反应肯定是直接对每一个求职者搜索所有的岗位,从而找到求职者合适的岗位。但这种方法效率极低(大部分岗位肯定是技能对不上的),而且无法进行性能扩展。 P181
使用类似上面提到的附加值形式,每次添加一个岗位时,在对应的技能集合中添加这个岗位的 id ( SADD idx:skill:{skill} {job_id} ),再在岗位有序集合中进行添加,成员为岗位 id ,成员的分值为所需的技能数量 ( ZADD job_required_skill_count {job_id} {required_skill_count} )。搜索的时候就先对求职者所有技能对应的集合使用 ZUNIONSTORE *** 作计算每个公司匹配的技能数量 ( ZUNIONSTORE matched {n} idx:skill:{skill} WEIGHTS 1 ),然后再与岗位有序集合求交集,并让公司有序集合的权重为 -1 ( ZINTERSTORE result 2 job_required_skill_count matched WEIGHTS -1 1 ),最后获取分值为 0 的所有岗位即可完成搜索。 P181
所思
书上的这个方法比较麻烦,其实可以使用文章最开始的无序倒排索引,岗位相当于要搜索的文档,岗位所需的技能相当于单词。
public void test2Trans() {
long start = SystemcurrentTimeMillis();
Transaction tx = jedismulti();
try{
for (int i = 0; i < 100000; i++) {
txset("t" + i, "t" + i);
}
}catch(Exception e){
txdiscard();
}
List results = txexec();
long end = SystemcurrentTimeMillis();
Systemoutprintln("Transaction SET: " + ((end - start)/10000) + " seconds");
}
我们知道Redis默认有16个数据库,默认是第0个数据库,那么如果在需要对数据库进行切换的时候,我们就可以使用下面这个命令:
使用如下命令进行切换
如果想要清除指定某一个数据库的数据
清除所有数据库的数据
接下来这个命令应该是最常用的了
平常在开发中,我们还需要经常对key进行判断,判断其是否存在
因为我们设置的缓存数据一般都不能是永久的,这个时候就需要我们在存储数据的时候,就为其设置过期时间。
string类型是Redis中五大基本数据类型之一,这也是最常使用到的一个数据类型,所有很多小伙伴们对Redis的认识和 *** 作就仅仅的停留在了对Redis的 *** 作层面,但是你是否知道string类型中的相关命令,还是有非常多实用的
接下来先看一下对string类型进行基本存储和获取的命令。
如果我们存储的string中的内容是数字的话,我们也可以对其进行增或减 *** 作,Redis可以自动的对字符串进行相关的 *** 作。实现的命令如下:
使用msetnx时,同时设置一个或多个 key-value 对,当且仅当所有给定 key都不存在时才成立。
getset命令从字面意思就可以看出来,他的作用是先get再set。
总结string类似的使用场景:
在使用list类型进行存取的时候,有两个命令需要进行区分:
注意:只有pop和push才分左右,其他的l都是list的意思
总结:
总结set集合一般用于元素的不重复的场景,比如抽奖系统,轮播等场景下
在使用hash集合的时候,要注意,hash其实就是一个Map集合,key-map的时候,值是一个map集合的形式进行存储的,也和Java中的hashmap有一个类似。
HVALS获取所有的value,HKEYS获取所有的key,HGETALL获取所有的键值
总结:
hash可以用于存储变更的数据,比如user,name,age等,尤其是用户信息之类的,hash更加适合用于对象的存储,string更加适合用于字符串的存储。
在set集合的基础上增加一个序列号,来进行排序
ZRANGEBYSCORE使用语法
总结
以上是在对五种数据类型进行存取时的一些常用命令 *** 作。关于其他的命令使用,小伙伴们在用到的时候可以直接入官网查看就可以了。
取值的方式有很多种,这个要根据需求来定:比如返回第一个集合与其他集合之间的差异,可以使用SDIFF key1 [key2] ,移除并返回集合中的一个随机元素,可以使用SPOP key
以上就是关于python 获取的redis里的数据怎么处理全部的内容,包括:python 获取的redis里的数据怎么处理、关于redis批量获取数据pipeline、Redis 实战 —— 10. 实现内容搜索、定向广告和职位搜索等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)