上一篇文章:Python--Redis实战:第三章:Redis命令:第六节:发布与订阅
下一篇文章:Python--Redis实战:第四章:数据安全与性能保障:第1节:持久化选项

到目前为止,本章介绍了Redis提供的5种结构以及Redis的发布与订阅模式。本节将要介绍的命令则可以用于处理多种类型的数据:首先要介绍的是可以同时处理字符串、集合、列表和散列的sort命令;之后要介绍的是用于实现基本事务特性的multi命令和exec命令,这两个命令可以让用户将多个命令当做一个命令来执行;最后要介绍的是几个不同的自动过期命令,亚麻可以自动删除无用的数据。

阅读本节有助于读者更好的理解如何同时组合和操作多种数据类型。

排序

Redis的排序操作和其他编程语言的排序操作一样,都可以根据某种比较规则对一系列元素进行有序排列。负责执行排序操作的sort命令可以根据字符串、列表、集合、有序集合、散列这5种键Kim存储的数据,对列表、集合以及有序集合进行排序。如果读者之前曾经使用过关系数据库的话,那么可以将soft命令看做是sql语言里的order by。

下表展示了sort命令的定义:

命令 用例 用例描述
soft soft source-key [by pattern] [limit offset count] [get pattern get pattern ...]] [asc/desc] [alph] [store dest-key] 根据给定的选项,对输入列表、集合或者有序集合进行排序,然后返回或者存储排序的结果。

使用sort命令提供的选项可以实现以下功能:

  • 根据降序而不是默认的升序来排列元素;
  • 将元素看作是数字来进行排序,或者将元素看作是二进制字符串来进行排序(比如排序字符串'110'和'12'的排序结果就跟排序数字110和12的结果不一样);
  • 使用被排序元素之外的其他值作为权重进行排序,甚至还可以从输入的列表、集合、有序集合以外的其他地方进行取值。

实例

import redis # 导入redis包包# 与本地redis进行链接,地址为:localhost,端口号为6379
r = redis.StrictRedis(host='localhost', port=6379)
r.delete('sort-input')#首先将一些元素添加到列表里面
print(r.rpush('sort-input',23,15,110,7))
#根据数字大小对元素进行排序
print(r.sort('sort-input'))
#根据字母顺序对元素进行排序
print(r.sort('sort-input',alpha=True))#添加一些用于执行排序操作和获取操作的附加数据
print(r.hset('d-7','field',5))
print(r.hset('d-15','field',1))
print(r.hset('d-23','field',9))
print(r.hset('d-110','field',3))#将散列的域(field)用作权重,对sort-input列表进行排序
print(r.sort('sort-input',by='d-*->field'))#获取外部数据,并将它们用作命令的返回值,而不是返回被排序的数据
print(r.sort('sort-input',by='d-*->field',get='d-*->field'))

运行结果:

4
[b'7', b'15', b'23', b'110']
[b'110', b'15', b'23', b'7']
0
0
0
0
[b'15', b'110', b'7', b'23']
[b'1', b'3', b'5', b'9']

最开头的几行代码设置了一些初始数据,然后对这些数据进行了数值排序和字符串排序,最后的代码演示了如果通过sort命令的特殊语法来将散列存储的数据作为权重进行排序,以及怎样获取并返回散列存储的数据。

sort命令不仅可以对列表进行排序,还可以对集合进行排序,然后返回一个列表形式的排序结果。上述实例除了展示了如果使用alpha关键字参数对元素进行字符串排序之外,还展示了如果基于外部数据对元素进行排序,以及如何获取并返回外部数据。

后面讲介绍如何组合使用集合操作和sort命令:当集合结构计算交集、并集和差集的能力,与sort命令获取散列存储的外部数据的能力相结合时,sort命令将变得非常强大。

尽管sort是Redis中唯一一个可以同时处理3种不同类型的数据的命令,但基本的Redis事务同样可以让我们在一连串不断执行的命令里面操作多种不同类型的数据。

基本的Redis事务

有时候为了同时处理多个结构,我们需要向Redis发送多个命令。尽管Redis有几个可以在两个键之间复制或者移动元素,但却没有那种可以在两个不同类型之间移动元素的命令(虽然可以使用zunionstore命令将元素从一个集合复制到一个有序集合)。为了对相同或者不同类型的多个键执行操作,Redis有5个命令可以让用户在不被打断(interruption)的情况下对多个键执行操作,它们分别是watch、multi、exec、unwatch、discard。

这一节中介绍最基本的Redis事务用法,其中只会用到multi命令和exec命令。

什么是Redis的基本事务

Redis的基本事务需要用到multi命令和exec命令,这种事务可以让一个客户端在不被其他客户端打断的情况下执行多个命令。和关系数据库那种可以在执行的过程中进行回滚(rollback)的事务不同,在Redis里面,被multi命令和exec命令包围的所有命令会一个接一个的执行,直到所有命令都执行完毕。当一个事务执行完毕之后,Redis才会处理其他客户端的命令。

要在Redis里面执行事务,我们首先需要执行multi命令,然后输入那些我们想要在事务里面执行的命令,最后再执行exec命令。当Redis从一个客户端那里接受到multi命令时,Redis会将这个客户端之后发送的所有命令都放入到一个队列里面,直到这个客户端发送exec命令为止,然后Redis就会在不被打断的情况下,一个接一个地执行存储在队列里面的命令。从语义上来说,Redis事务在Python客户端上面是由流水线(pipelien)实现:对连接对象用pipeline()方法将创建一个事务,在一切正常的情况下,客户端会自动地使用multi和exec包裹起用户输入的多个命令。此处,为了减少Redis与客户端之间的通信往返次数,提升执行多个命令时的性能,Python的Redis客户端会存储起事务包含的多个命令,然后在事务执行时一次性地将所有命令都发送给Redis。

跟介绍publish命令和subscribe命令时的情况一样,要展示事务执行结果,最简单的方法就是将事务放到线程里执行。

下面代码展示了在没有使用事务的情况下,执行并行(parallel)自增操作的结果:

import redis  # 导入redis包包
import time,threading# 与本地redis进行链接,地址为:localhost,端口号为6379
r = redis.StrictRedis(host='localhost', port=6379)
r.delete('notrans:')def notrans():#对'notrans:'计数器执行自增操作并打印操作的执行结果print(r.incr('notrans:'))#等待100毫秒time.sleep(.1)#对'notrans:'计数器执行自减操作。r.incr('notrans:',-1)if __name__ == '__main__':# 启动3个线程来执行没有被事务包裹的自增、休眠和自减操作for i in range(3):threading.Thread(target=notrans).start()# 等待500毫秒,让操作有足够的时间完成time.sleep(.5)

结果:

1
2
3

因为没有使用事务,所以三个线程都可以在执行自减操作之前,对notrans:计数器执行自增操作。虽然代码里面通过休眠100毫秒放大了潜在问题,但如果我们确实需要在不受其它命令干扰的情况下,对计数器执行自增操作和自减操作,那么我们就不得不解决这个潜在问题。

下面代码使用事务来执行相同的操作:

import redis  # 导入redis包包
import time,threading# 与本地redis进行链接,地址为:localhost,端口号为6379
r = redis.StrictRedis(host='localhost', port=6379)
r.delete('trans:')def notrans():#创建一个事务型(transactional)流水线对象pipeline=r.pipeline()#把针对'trans:'计数器的自增操作放入队列pipeline.incr('trans:')#等待100毫秒time.sleep(.1)#把针对'trans:'计数器的自减操作放入队列pipeline.incr('trans:',-1)#执行被事务包裹的命令,并打印自增操作的执行结果print(pipeline.execute()[0])if __name__ == '__main__':# 启动3个线程来执行没有被事务包裹的自增、休眠和自减操作for i in range(3):threading.Thread(target=notrans).start()# 等待500毫秒,让操作有足够的时间完成time.sleep(.5)

结果:

1
1
1

可以看出,尽管自增操作和自减操作直接有一段延迟时间,但通过使用事务,各个线程都可以在不被其它线程打断的情况下,执行各自队列里面的命令。记住,Redis要在接收到Exec命令之后,才会执行那些位于multi和exec之间的入队命令。

在使用Redis存储数据的时候,有些数据仅在一段很短的时间内有用,虽然我们可以在数据的有效期过了之后删除无用的数据,但更好的办法是使用Redis提供的键过期操作来自动删除无用数据。

键的过期时间

在使用Redis存储数据的时候,有些数据可能在某个时间点之后就不再有用了,用户可以使用DEL命令显示删除这些无用数据,也可以通过Redis的过期时间(expiration)特征来让一个键再给定的时限(timeout)之后自动被删除。当我们说一个键【带有生存时间】(time to live)或者一个键【会在特定时间之后过期】时,我们指的是Redis会在这个键的过期时间到达时自动删除该键。

虽然过期时间特性对于清理缓存数据非常有用,不过通常只有少数几个命令可以原子地为键设置过期时间,并且对于列表、集合、散列和有序集合这样的容器来说,键过期命令只能为整个键设置过期时间,而没办法为键里面的单个元素设置过期时间(为了解决这个问题,可以使用存储时间戳的有序集合来实现针对的那个元素的过期操作)。

本节将对那些可以在给定时限或者给定时间之后,自动删除过期键的Redis命令进行介绍。通过阅读本节,读者可以学会如何使用过期操作来自动删除过期数据并降低Redis的内存占用。

下表列出了Redis提供的用于为键设置过期时间的命令,已经查看键的过期时间的命令:

命令 示例 描述
persist persist key-name 移除键的过期时间
ttl ttl key-name 查看给定键距离过期还有多少秒
expire expire key-name seconds 让给定键再指定的秒数之后过期
expireat expireat key-name timestamp 将给定键的过期时间设置为给定的UNIX时间戳。
pttl pttl key-name 查看给定键距离过期时间还有多少毫秒,这个命令在Redis2.6或以上版本可用,
pexpire pexpire key-name milliseconds 让给定键再指定的毫秒之后过期。这个命令在Redis2.6或以上版本可用。
pexpireat pexpireat key-name timestamp-milliseconds 将一个毫秒级精确的UNIX时间戳设置为给定键的过期时间,这个命令在Redis2.6或以上版本可用。

下面代码展示了几个对键执行过期时间操作的例子:

import redis # 导入redis包包
import time# 与本地redis进行链接,地址为:localhost,端口号为6379
r = redis.StrictRedis(host='localhost', port=6379)
r.delete('trans:')#设置一个简单的字符串值作为过期时间的设置对象
print(r.set('key','value'))
print(r.get('key'))
print(r.expire('key',2))time.sleep(1)#查看键距离过期还有多长时间
print(r.ttl('key'))time.sleep(1)#此时键已经过期,并被删除
print(r.get('key'))

运行结果:

True
b'value'
True
1
None

上一篇文章:Python--Redis实战:第三章:Redis命令:第六节:发布与订阅
下一篇文章:Python--Redis实战:第四章:数据安全与性能保障:第1节:持久化选项

Python--Redis实战:第三章:Redis命令:第七节:其他命令相关推荐

  1. 零基础学Python课后实战第三章

    零基础学Python课后实战第三章 实战一:模拟支付宝蚂蚁森林的能量产生过程 实战二:猜数字游戏 实战三:模拟跳一跳小游戏的加分块 实战四:模拟10086查询功能 实战一:模拟支付宝蚂蚁森林的能量产生 ...

  2. Web前端开发笔记——第三章 CSS语言 第七节 圆角边框、阴影

    目录 前言 一.圆角边框 (一)border-×-×-radius (二)border-radius 二.阴影 (一)基本阴影设置 (二)内部阴影设置 结语 前言 本节介绍仅在CSS3中的新内容,例如 ...

  3. Python精确指南——第三章 Selenium和爬虫

    3       Selenium 3.1     介绍 网络爬虫在互联网领域有着广泛的应用. Selenium是一个页面自动化控制框架.能够模拟实际操作,自动化获取网站提供的页面资源信息. Selen ...

  4. Redis数据库(三)——Redis数据类型

    Redis数据库(三)--Redis数据类型 一.String类型 1.set / get / append / strlen 2.incr / decr / incrby / decrby 3.ge ...

  5. 零基础学Python课后实战第六章

    零基础学Python课后实战第六章 tips 实战一:导演为剧本选主角 实战二:模拟美团外卖商家的套餐 实战三:根据生日判断星座 实战四:将美元转换为人民币 tips 格式化字符串: {:0>9 ...

  6. 零基础学Python课后实战第四章

    零基础学Python课后实战第四章 实战一:输出王者荣耀的游戏角色 实战二:模拟火车订票系统 实战三:电视剧的收视率排行榜 tips 实战一:输出王者荣耀的游戏角色 列表的创建.遍历列表 代码 pri ...

  7. Python爬虫学习第三章-4.3-使用xpath解析爬取全国城市名称

    Python爬虫学习第三章-4.3-使用xpath解析爬取全国城市名称   这一节主要是使用xpath解析爬取全国城市名称 这里使用的网址是:空气质量历史数据查询   这一个案例体现的点主要是xpat ...

  8. Web前端开发笔记——第三章 CSS语言 第四节 CSS列表、表格样式

    目录 一.CSS列表样式 (一)设计列表项前标志类型 (二)设计列表项前标志位置 (三)设计列表项图片 (四)设计整体列表属性 二.CSS表格样式 (一)设计表格大小 (二)设计表格边框 (三)奇偶选 ...

  9. 【重识云原生】第三章云存储3.5节——商用分布式云存储方案

    <重识云原生系列>专题索引: 第一章--不谋全局不足以谋一域 第二章计算第1节--计算虚拟化技术总述 第二章计算第2节--主流虚拟化技术之VMare ESXi 第二章计算第3节--主流虚拟 ...

  10. 【重识云原生】第三章云存储3.2节——SPDK方案综述

    <重识云原生系列>专题索引: 第一章--不谋全局不足以谋一域 第二章计算第1节--计算虚拟化技术总述 第二章计算第2节--主流虚拟化技术之VMare ESXi 第二章计算第3节--主流虚拟 ...

最新文章

  1. 在Qt调用OpenCV库编写GUI程序
  2. MVC-RedirectToAction跳转到其他Area
  3. LinkedHashSet类
  4. SQLIntegrityConstraintViolationException: 异常解决
  5. Spring Bean的配置及常用属性
  6. python条件语句有哪些_Python 条件语句
  7. shell之for循环的3个简单脚本
  8. struts2.5通配符使用异常
  9. 团队作业4——第一次项目冲刺(Alpha版本)2nd day
  10. Swift - 动画效果的实现方法总结(附样例)
  11. javascript中Object类原型对象的属性和方法
  12. 如何成功发布一个MSMQ的Windows服务
  13. 计算机考试系统客户端网址,[中学]计算机基础测评系统考试客户端操作步骤.doc...
  14. c语言程序设计商品库存管理系统,《C语言课程设计商品库存管理系统》.doc
  15. 硕士学位论文多级标题编号与图表编号
  16. android自定义View 中秋节放个烟花吧~
  17. 去除Android状态栏的广告推送
  18. 失落世界服务器国庆宝箱位置,失落的斯菲尔 图文攻略 全剧情任务流程全宝箱收集...
  19. [洛谷]CON1466 洛谷2017春节联欢赛 Hello Dingyou题解 Bzoj4763雪辉
  20. 计算机中的位,字节,字,字长的概念

热门文章

  1. python清洗数据用什么包_格式化和清洗数据的Python工具包
  2. anaconda python_机器学习用Python—Python集成工具包Anaconda安装步骤
  3. 万用表怎么测量电池容量_家电常识丨万用表的测量应用学习
  4. 《深入理解Java函数式编程》系列文章
  5. PCA主成分分析 特征降维 opencv实现
  6. 小氓男-灰色按钮激活V1.0
  7. JS收集:限制输入搜索串
  8. Qt Quick 中 QML 与 C++ 混合编程详解
  9. c#中将WM_CLOSE消息发送到没有窗口的进程的方法
  10. mysql的联表查询和去重复数据