基于python操纵redis入门介绍

by:授客  QQ:1033553122

测试环境

redis-3.0.7

CentOS 6.5-x86_64

python 3.3.2

基于Python操作Redis

Redis客户端实例是线程安全的,可以直接将Redis连接实例设置为一个全局变量,直接使用。如果需要另一个Redis实例,就需要重新创建redis连接实例来获取一个新的连接
 
示例
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
__author__ = 'shouke'
 
import redis
 
if __name__ == '__main__':
    r = redis.StrictRedis(host='192.168.1.103', port=6379, db='0')
    result = r.set('name', 'shouke'# 存储键-
    print('result of set: %s' % result)
 
    r.set('hobby', 'music')
 
    name = r.get('name'# 获取键“name”对应的值
    print('name: %s' % name)
 
    keys = r.keys()  # 获取所有键
    print('keys: %s' % keys)
 
    dbsize = r.dbsize() # redis数据库包的记录数(key的数量)
    print('dbsize: %s' % dbsize)
 
    result = r.delete('hobby'# 根据指定的键,删除指定键-
    print('result of delete: %s' % result)
 
    result = r.save()  # 执行检查点操作,将数据写回磁盘。保存时阻塞
    print('result of save: %s' % result)
 
    hobby = r.get('hobby')
    print('hobby: %s' % hobby)
 
    name = r['name']   # 获取键“name”对应的值
    print('name: %s' % name)
 
    result = r.flushdb()   # 清空数据当前库中的所有数据
    print('result of flushdb: %s' % result)
 
    print('dbsize: %s' % r.dbsize())
结论:
result of set: True
name: b'shouke'
keys: [b'name', b'hobby']
dbsize: 2
result of delete: 1
result of save: True
hobby: None
name: b'shouke'
result of flushdb: True
dbsize: 0
 
连接池
redis-py使用连接池来关联连接到Redis服务器的连接。默认的,每个Redis实例会按顺序创建自己的连接池。可以重写该行为,如下:
pool = redis.ConnectionPool(host='192.168.1.103', port=6379, db=0)
r = redis.Redis(connection_pool=pool)
 
连接
连接池管理一系列的连接实例。redis-py拥有两种类型的连接。默认的,Connection基于普通TCP socket的连接,UnixDomainSocketConnection允许运行在相同设备的客户端作为服务器,通过一个unix domain socket进行连接,使用示例如下:
r = redis.Redis(unix_socket_path='/tmp/redis.sock')
 
注:确保在redis.conf文件中定义了unixsocket参数(默认的,该参数已被注释掉)
 
也可以创建自己的Connection子类
pool = redis.ConnectionPool(connection_class=YourConnectionClass,
                                your_arg='...', ...)
 
解析器Parsers
redis-py有两种paser类,PythonParser和HiredisParser。默认的,redis-py会试图使用HiredisParser如果已安装hiredis模块,且否则使用PythonParser。使用Hiredis可以大大提高解析返回结果的速度。
 
 
响应回调
客户端类使用了一系列的回调来转换Redis响应为适当的python类型。这类回调函数在Redis客户端类一个名叫RESPONSE_CALLBACKS的字典中进行了定义了。
 
使用set_response_call方法可以为每个实例添加客户端回调。该方法接收两个参数:命令行名称和回调。这种方式添加的回调函数仅在被添加的实例有效。如果想定义或重写全局的回调函数,可以定一个Redis的子类并添加回调用到REDIS_CALLBACKS字典。
 
管道(Pipelines)
Redis类的子类,在单一请求中缓冲发往服务器的多条命令。通过减少往返于服务器和客户端之间TCP包数量,显著的提高分组命令的执行性能。
 
示例
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
__author__ = 'shouke'
import redis
 
if __name__ == '__main__':
    pool = redis.ConnectionPool(host='192.168.1.103', port=6379, db=0)
    r = redis.Redis(connection_pool=pool)
    result = r.set('name', 'shouke')
    print(result)
 
    pipe = r.pipeline() # 创建一个管道实例
    result = pipe.set('name2', 'ishouke')
    print(result)
 
    result = pipe.get('name2')
    print(result)
 
    result = pipe.execute()  # 把所有缓冲命令发送到服务器,返回一个列表,包含每个命令的执行结果
    print(result)
 
运行结果:
True
Pipeline>>
Pipeline>>
[True, b'ishouke']
 
注:重复运行的情况下,如果key重复了,redis默认直接覆盖旧值
 
也可以改成如下方式
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
__author__ = 'shouke'
import redis
 
if __name__ == '__main__':
    pool = redis.ConnectionPool(host='192.168.1.103', port=6379, db=0)
    r = redis.Redis(connection_pool=pool)
 
    pipe = r.pipeline()
    name2 = []
    result = pipe.set('name', 'shouke').sadd('ishouke', 'name').incr('num').execute()
    print(result)
    print(r.keys())
 
运行结果:
[True, 1, 1]
[b'ishouke', b'name', b'num']
 
incr指定的键不能和sadd,set中指定的键相同,否则可能报错,类似如下:
redis.exceptions.ResponseError: Command # 3 (INCRBY name2 1) of pipeline caused error: WRONGTYPE Operation against a key holding the wrong kind of value
 
默认的情况下,管道中缓冲的指命令组为一个原子操作,执行
pipe = r.pipeline(transaction=False)   可以禁用这一特性。
 
一个常见的问题:在进行原子事务操作前,需要优先从Redis中获取数据,例如,假设INCR命令不存在,且需要用python编译一个原子版本的INCR
 
一个不成熟的本地实现是先GET值,然后在python中增加它,然后SET值。然而,这并不是一个原子性的,因为多个客户端可以同时做这件事情,每一个客户端都通过GET获取相同的值。
 
WATCH命令提供了在开始一个事务之前监控一个或多个键值的能力。如果开始事务之前,任何一个key的值改变了,整个事务将被取消并抛出一个WatchError。为了完成我们自己客户端的INCR命令,我们可以如下方式实现:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
__author__ = 'shouke'
import redis
 
if __name__ == '__main__':
    pool = redis.ConnectionPool(host='192.168.1.103', port=6379, db=0)
    r = redis.Redis(connection_pool=pool)
 
    result = r.flushdb()
    with r.pipeline() as pipe:
        while 1:
            try:
              # 对序列号的键进行 WATCH
                pipe.watch('OUR-SEQUENCE-KEY')
              # WATCH 执行后,pipeline 被设置成立即执行模式直到我们通知它重新开始缓冲命令这就允许我们获取序列号的值
                current_value = pipe.get('OUR-SEQUENCE-KEY')
                next_value = int(current_value) + 1
 
                pipe.multi() # MULTI 命令把 pipeline 设置成缓冲模式
                pipe.set('OUR-SEQUENCE-KEY', next_value)
                pipe.execute()
                break
            except Exception:
              # 一定是其它客户端在我们开始 WATCH 和执行 pipeline 之间修改了'OUR-SEQUENCE-KEY',最好的选择是重试
                continue
注意:WATCH期间,因为管道必须绑定到一个连接,特别注意,必须调用reset()使得连接返回到连接池。如果管道是作为Context Manager(如上面的例子所示),将会自动调用reset().当然也可以手动显示的调用。
>>> pipe = r.pipeline()
>>> while 1:
...     try:
...         pipe.watch('OUR-SEQUENCE-KEY')
...         ...
...         pipe.execute()
...         break
...     except WatchError:
...         continue
...     finally:
...         pipe.reset()
 
扫描迭代器
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
__author__ = 'shouke'
import redis
 
if __name__ == '__main__':
    pool = redis.ConnectionPool(host='192.168.1.103', port=6379, db=0)
    r = redis.Redis(connection_pool=pool)
    for key, value in (('A', '1'), ('B', '2'), ('C', '3')):
        r.set(key, value)
 
    for key in r.scan_iter():
        print(key, r.get(key))
 
运行结果:
b'C' b'3'
b'B' b'2'
b'A' b'1'
 
说明:类似的还有hscan_iter, sscan_iter and zscan_iter等迭代器
 
 
incr命令
示例:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
__author__ = 'shouke'
import redis
 
if __name__ == '__main__':
    pool = redis.ConnectionPool(host='192.168.1.103', port=6379, db=0)
    r = redis.Redis(connection_pool=pool)
 
    r.set('num_increase_continuously', 1)
 
    result = r.get('num_increase_continuously')
    print(result)
 
    result = r.incr('num_increase_continuously')
    print(result)
 
    result = r.incr('num_increase_continuously')
    print(result)
 
    result = r.get('num_increase_continuously')
    print(result)
 
运行结果:
b'1'
2
3
b'3'
 
说明:
incr(self, key, amount=1):根据amount增加key的值,每执行一次增加amount,返回结果为增加后的值,如果key不存在,则key的值被初始化为amount
 
 
sadd指令
 
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
__author__ = 'shouke'
 
import redis
 
if __name__ == '__main__':
    pool = redis.ConnectionPool(host='192.168.1.103', port=6379, db=0)
    r = redis.Redis(connection_pool=pool)
 
    result = r.sadd('user:user_tb', 'username')
    print('result of sadd username: %s' % result)
 
    result = r.sadd('user:user_tb', 'hobby')
    print('result of sadd hobby: %s' % result)
 
运行结果:
result of sadd username: 1
result of sadd hobby: 1
 
注:
sadd(self, name, *values): 添加到value(s)到集合name中
 
sismember指令
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
__author__ = 'shouke'
 
import redis
 
if __name__ == '__main__':
    pool = redis.ConnectionPool(host='192.168.1.103', port=6379, db=0)
    r = redis.Redis(connection_pool=pool)
 
    r.sadd('user:user_tb', 'username')
    result = r.sismember('user:user_tb', 'username')
    print(result)
 
注:
sismember(self, name, value):判断value是否是name集合的成员,是则返回True,反之False
 
smembers指令
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
__author__ = 'shouke'
 
import redis
 
if __name__ == '__main__':
    pool = redis.ConnectionPool(host='192.168.1.103', port=6379, db=0)
    r = redis.Redis(connection_pool=pool)
 
    r.sadd('user:user_tb', 'username')
    r.sadd('user:user_tb', 'hobby')
 
    result = r.smembers('user:user_tb')
    print(result)
 
运行结果:
{b'username', b'hobby'}
 
smembers(self, name):返回集合name的所有成员
 
sunion指令
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
__author__ = 'shouke'
 
import redis
 
if __name__ == '__main__':
    pool = redis.ConnectionPool(host='192.168.1.103', port=6379, db=0)
    r = redis.Redis(connection_pool=pool)
 
    r.sadd('user:user_tb', 'username')
    r.sadd('user:user_tb', 'hobby')
    r.sadd('order:order_goods', 'username')
 
    result = r.sunion('order:order', 'user:user_tb')
    print(result)
 
运行结果:
{b'hobby', b'username'}
 
注:
sunion(self, keys, *args):根据指定的keys返回集合的并集
 
sinter指令
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
__author__ = 'shouke'
 
import redis
 
if __name__ == '__main__':
    pool = redis.ConnectionPool(host='192.168.1.103', port=6379, db=0)
    r = redis.Redis(connection_pool=pool)
 
    r.sadd('user:user_tb', 'username')
    r.sadd('user:user_tb', 'hobby')
    r.sadd('order:order_goods', 'username')
 
    result = r.sinter( 'order:order_goods', 'user:user_tb')
    print(result)
 
运行结果:
{b'username'}
 
注:
sinter(self, keys, *args):根据指定的keys返,返回集合交集,为空则返回set()
 
 
hset指令
实现散列表的存储
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
__author__ = 'shouke'
 
import redis
 
if __name__ == '__main__':
    pool = redis.ConnectionPool(host='192.168.1.103', port=6379, db=0)
    r = redis.Redis(connection_pool=pool)
 
    result = r.hset('user:user_tb', 'name', 'shouke')
    print('result of hset: %s' % result)
 
    r.hset('user:user_tb', 'hobby', 'music')
    r.hset('user:user_tb', 'addr', '深圳')
 
    result = r.hincrby('user:user_tb', 'signin', 1)
    print('result of hincrby: %s' % result)
 
    result = r.hincrby('user:user_tb', 'signin', 1)
    print('result of hincrby: %s' % result)
 
    result = r.hgetall('user:user_tb')
    print('result of hgetall: %s' % result)
 
    result = r.hkeys('user:user_tb')
    print('result of hkeys: %s' % result)
 
运行结果:
result of hset: 1
result of hincrby: 1
result of hincrby: 2
result of hgetall: {b'hobby': b'music', b'addr': b'\xe6\xb7\xb1\xe5\x9c\xb3', b'name': b'shouke', b'signin': b'2'}
result of hkeys: [b'name', b'hobby', b'addr', b'signin']
 
注:
hincrby(self, name, key, amount=1):根据amount增加哈希name中key的值,每执行一次就增加amount,返回结果为key增加后的值
 
hset(self, name, key, value):在哈希name中添加键值对key-value,添加成功则返回1,否则返回0
 
hget(self, name, key):返回哈希name中,key的值
 
hgetall(self, name):返回包含哈希键值对(name/value)的字典 pairs"
 
hkeys(self, name):返回哈希name中的key的列表
 
参考连接:
https://pypi.python.org/pypi/redis#downloads
http://debugo.com/python-redis/
 
更多资料烦查看源代码

Python 基于python操纵redis入门介绍的更多相关文章

  1. Redis(二):Redis入门介绍

    Redis入门介绍目录导航: 入门概述 VMWare + VMTools千里之行始于足下 Redis的安装 Redis启动后杂项基础知识讲解 入门概述 是什么 Redis:REmote DIction ...

  2. Python 基于Python实现的ssh兼sftp客户端(上)

    基于Python实现的ssh兼sftp客户端   by:授客 QQ:1033553122 实现功能 实现ssh客户端兼ftp客户端:实现远程连接,执行linux命令,上传下载文件 测试环境 Win7 ...

  3. Python 基于python操纵zookeeper介绍

    基于python操纵zookeeper介绍 by:授客  QQ:1033553122 测试环境 Win7 64位 Python 3.3.4 kazoo-2.6.1-py2.py3-none-any.w ...

  4. Python 基于python+mysql浅谈redis缓存设计与数据库关联数据处理

    基于python+mysql浅谈redis缓存设计与数据库关联数据处理 by:授客  QQ:1033553122 测试环境 redis-3.0.7 CentOS 6.5-x86_64 python 3 ...

  5. Python 基于Python及zookeeper实现简单分布式任务调度系统设计思路及核心代码实现

    基于Python及zookeeper实现简单分布式任务调度系统设计思路及核心代码实现   by:授客 QQ:1033553122 测试环境 功能需求 实现思路 代码实践(关键技术点实现) 代码模块组织 ...

  6. Python 基于Python结合pykafka实现kafka生产及消费速率&主题分区偏移实时监控

    基于Python结合pykafka实现kafka生产及消费速率&主题分区偏移实时监控   By: 授客 QQ:1033553122   1.测试环境 python 3.4 zookeeper- ...

  7. Python 基于Python从mysql表读取千万数据实践

    基于Python 从mysql表读取千万数据实践   by:授客 QQ:1033553122 场景:   有以下两个表,两者都有一个表字段,名为waybill_no,我们需要从tl_waybill_b ...

  8. Python 基于Python实现的ssh兼sftp客户端(下)

    基于Python实现的ssh兼sftp客户端   by:授客 QQ:1033553122 otherTools.py #!/usr/bin/env/ python # -*- coding:utf-8 ...

  9. Python基于Python实现批量上传文件或目录到不同的Linux服务器

    基于Python实现批量上传文件或目录到不同的Linux服务器   by:授客 QQ:1033553122 实现功能 1 测试环境 1 使用方法 1 1. 编辑配置文件conf/rootpath_fo ...

随机推荐

  1. Python模块——xml

    xml模块 xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单, 不过,古时候,在json还没诞生的黑暗年代,大家只能选择用xml呀,至今很多传统公司如金融行 ...

  2. 【转】php结合redis实现高并发下的抢购、秒杀功能

    抢购.秒杀是如今很常见的一个应用场景,主要需要解决的问题有两个:1 高并发对数据库产生的压力2 竞争状态下如何解决库存的正确减少("超卖"问题)对于第一个问题,已经很容易想到用缓存 ...

  3. Nginx+Keepalived 实现高可用

    Keepalived 是一个高性能的 服务器高可用 或 热备解决方案,Keepalived主要来防止服务器单点故障的问题,可以通过其与Nginx的配合来实现web服务端的高可用. Keepalived ...

  4. Linux 软件安装到 /usr,/usr/local/ 还是 /opt 目录?

    转自:https://blog.csdn.net/aqxin/article/details/48324377 Linux 的软件安装目录是也是有讲究的,理解这一点,在对系统管理是有益的 /usr:系 ...

  5. 基于Flume的日志收集系统方案参考

    前言 本文将简单介绍两种基于Flume的日志收集系统可能的架构方案,可根据不同的实际场景参考使用. 方案一 示例图如下: 说明: 每个日志源(http上报.日志文件等)对应一个Agent-c用于收集对 ...

  6. Java NIO中的缓冲区Buffer(一)缓冲区基础

    什么是缓冲区(Buffer) 定义 简单地说就是一块存储区域,哈哈哈,可能太简单了,或者可以换种说法,从代码的角度来讲(可以查看JDK中Buffer.ByteBuffer.DoubleBuffer等的 ...

  7. Kafka实战-实时日志统计流程

    1.概述 在<Kafka实战-简单示例>一文中给大家介绍来Kafka的简单示例,演示了如何编写Kafka的代码去生产数据和消费数据,今天给大家介绍如何去整合一个完整的项目,本篇博客我打算为 ...

  8. Docker国内仓库和镜像

    由于网络原因,我们在pull Image 的时候,从Docker Hub上下载会很慢...所以,国内的Docker爱好者们就添加了一些国内的镜像(mirror),方便大家使用. 一.国内Docker仓 ...

  9. PHP序列化变量的4种方法

    序列化是将变量转换为可保存或传输的字符串的过程:反序列化就是在适当的时候把这个字符串再转化成原来的变量使用.这两个过程结合起来,可以轻松地存储和传输数据,使程序更具维护性. 1.  serialize ...

  10. git第七节---git merge和git rebase

    # git merge和git rebase 都可以进行分支合并 #git merge 合并后保留记录两个分支的记录 #git rebase合并后会展示成一个分支的记录,另一个分支的提交实际生成了一个 ...