Python 随笔之Redis
Python学习记录 ——redis
2018-03-07
Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。redis是一个key-value存储系统(线程安全)。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)和zset(有序集合)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
Linux安装redis
wget http://download.redis.io/releases/redis-3.0.6.tar.gz
tar -xzf redis-3.0.6.tar.gz
cd redis-3.0.6
make
LInux终端使用redis
[sunqi@localhost src]$ ./redis-server#启动redis服务
[sunqi@localhost src]$ ./redis-cli #启动redis客户端
127.0.0.1:6379> #连接成功,默认本地6379端口
127.0.0.1:6379> set age 123
OK
127.0.0.1:6379> get age
""
127.0.0.1:6379> set age 3 ex 5#设置key生存时间,到期后会自动销毁
OK
127.0.0.1:6379> get age
""
127.0.0.1:6379> get age
(nil)
在进行Python操作redis之前先用cmd控制简单连接一下redis进行试验便发现了问题我的Windows连接报错
redis.exceptions.ConnectionError: Error 10060 connecting to 192.168.30.129:6379. .
经过一番辛苦百度得知是因为Linux防火墙关闭了6379端口的对外访问,日!
解决这个问题用了我一晚上加一上午的时间,主要是因为前段时间学习的Linux知识,有点忘记了,看来不复习,不经常使用真的不行啊!
解决办法如下:
关闭防火墙
CentOS 7、RedHat 7 之前的 Linux 发行版防火墙开启和关闭( iptables ):
即时生效,重启失效
#开启 service iptables start #关闭 service iptables stop
重启生效
#开启 chkconfig iptables on #关闭 chkconfig iptables off
CentOS 7、RedHat 7 之后的 Linux 发行版防火墙开启和关闭( firewall ):
systemctl stop firewalld.service
开放端口
CentOS 7、RedHat 7 之前的 Linux 发行版开放端口
#命令方式开放5212端口命令 #开启5212端口接收数据 /sbin/iptables -I INPUT -p tcp --dport 5212 -j ACCEPT #开启5212端口发送数据 /sbin/iptables -I OUTPUT -p tcp --dport 5212 -j ACCEPT #保存配置 /etc/rc.d/init.d/iptables save #重启防火墙服务 /etc/rc.d/init.d/iptables restart #查看是否开启成功 /etc/init.d/iptables status
CentOS 7、RedHat 7 之后的 Linux 发行版开放端口
firewall-cmd --zone=public --add-port=5121/tcp --permanent # --zone 作用域 # --add-port=5121/tcp 添加端口,格式为:端口/通讯协议 # --permanent 永久生效,没有此参数重启后失效
在我的LInux虚拟机敲入命令开放端口6379:
[root@localhost init.d]# systemctl stop firewalld.service
[root@localhost init.d]# firewall-cmd --zone=public --add-port=6379/tcp --permanent
一番庆祝:
C:\Users\1234567890>python
Python 2.7.12 (v2.7.12:d33e0cf91556, Jun 27 2016, 15:24:40) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import redis
>>> r = redis.Redis(host = '192.168.30.129',port = 6379)
>>> r.set('name','sunqi')
True
>>> print r.get('name')
sunqi
>>>
String操作:
redis中的String在在内存中按照一个name对应一个value来存储。
1、set
源码
def set(self, name, value, ex=None, px=None, nx=False, xx=False):
"""
Set the value at key ``name`` to ``value`` ``ex`` sets an expire flag on key ``name`` for ``ex`` seconds. ``px`` sets an expire flag on key ``name`` for ``px`` milliseconds. ``nx`` if set to True, set the value at key ``name`` to ``value`` only
if it does not exist. ``xx`` if set to True, set the value at key ``name`` to ``value`` only
if it already exists.
"""
中文翻译(我的理解):
ex:name的生存时间,单位秒,也就是ex= n n秒后name在内存中将不存在
px:生存时间,单位毫秒
nx:如果nx = True,当name不存在时,才会设置name-->value
xx:如果xx = True,当name已经存在时,才会设置name-->value
eg:
>>> r.set('sunqi','',ex=5)#生存时间为5秒
True
>>> print r.get('sunqi')
123
>>> print r.get('sunqi')
None
>>>
import redis r = redis.Redis(host='192.168.30.129', port=6379)
r.set('age','')
print(r.get('age'))
r.set('age','',nx=True)#age已经存在,设置nx不会改变age的value
print(r.get('age'))
r.set('age','',xx=True)#age已经存在,设置xx会改变age的value
print(r.get('age')) b''
b''
b'' Process finished with exit code 0
2、mset(*args, **kwargs)
批量设置值
如:
mset(k1='v1', k2='v2')
或
mget({'k1': 'v1', 'k2': 'v2'})
r.mset(k1='v1', k2='v2')
print(r.get('k1'))
print(r.get('k2'))
3.mget()
批量获取结果返回列表
r.mset(k1='v1', k2='v2')
print(r.mget('k1','k2'))
4.getset(name, value)
设置新值返回旧值
r.set('age','')
s = r.getset('age','')
print(r.get('age'))
print(s) b''
b'' Process finished with exit code 0
5.getrange(key, start, end)
获取子序列(根据字节获取,非字符)
r.set('name','kongdelin')
print(r.getrange('name',1,5)) b'ongde' Process finished with exit code 0
6.setrange(name, offset, value)
修改字符串内容,从指定字符串索引开始向后替换(新值太长时,则向后添加)
r.set('name','kongdelin')
r.setrange('name',6,'qwertyui')
print(r.get('name')) b'kongdeqwertyui' Process finished with exit code 0
7.setbit(name, offset, value)
对name对应值的二进制表示的位进行操作
先转换成ASCII码的二进制形式,然后对offset位进行修改
import redis
#setbit(name, offset, value)
r.set('a',3)
s = r.get('a')
print('before',r.get('a'))
print('bofore:',bin(ord(s.decode())))
r.setbit('a',6,0)
s = r.get('a')
print('after',r.get('a'))
print('after',bin(ord(s.decode())))
8.getbit(name, offset)
获取name对应的值的二进制表示中的某位的值 (0或1)
9.bitcount(key, start=None, end=None)
# 获取name对应的值的二进制表示中 1 的个数
# 参数:
# key,Redis的name
# start,位起始位置
# end,位结束位置
10.bitop(operation, dest, *keys)
# 获取多个值,并将值做位运算,将最后的结果保存至新的name对应的值 # 参数:
# operation,AND(并) 、 OR(或) 、 NOT(非) 、 XOR(异或)
# dest, 新的Redis的name
# *keys,要查找的Redis的name # 如:
bitop("AND", 'new_name', 'n1', 'n2', 'n3')
# 获取Redis中n1,n2,n3对应的值,然后讲所有的值做位运算(求并集),然后将结果保存 new_name 对应的值中
11.strlen(name)
返回name对应值的字节长度(一个汉字3个字节)
12.incr(self, name, amount=1)
# 自增 name对应的值,当name不存在时,则创建name=amount,否则,则自增。 # 参数:
# name,Redis的name
# amount,自增数(必须是整数)
13.decr(self, name, amount=1)
自减name对应的值
14.append(key, value)
# 在redis name对应的值后面追加内容 # 参数:
key, redis的name
value, 要追加的字符串
Hash操作
redis中Hash在内存中的存储格式如下图:
1.hset(name, key, value)
# name对应的hash中设置一个键值对(不存在,则创建;否则,修改) # 参数:
# name,redis的name
# key,name对应的hash中的key
# value,name对应的hash中的value
eg:
r.hset('sunqi','age1','')
r.hset('sunqi','age2','')
r.hset('sunqi','age3','')
print(r.hget('sunqi','age1'))
print(r.hget('sunqi','age2'))
print(r.hget('sunqi','age3'))
2.hmset()
# 在name对应的hash中批量设置键值对 # 参数:
# name,redis的name
# mapping,字典,如:{'k1':'v1', 'k2': 'v2'} # 如:
# r.hmset('xx', {'k1':'v1', 'k2': 'v2'})
eg:
r.hmset('sunqi',{'k1':'v1','k2':'v2'})
print(r.hmget('sunqi','k1','k2'))
3.hlen(name)
获取name对应的hash中键值对的个数
4.hgetall(name)
获取name对应
hash
的所有键值
5.hkeys(name)
获取name对应的hash中所有的key的值
6.hvals(name)
获取name对应的hash中所有的value的值
7.hdel(name,*keys)
将name对应的hash中指定key的键值对删除
8.hincrby(name, key, amount=1)
# 自增name对应的hash中的指定key的值,不存在则创建key=amount
# 参数:
# name,redis中的name
# key, hash对应的key
# amount,自增数(整数)
9.hscan(name, cursor=0, match=None, count=None)
# 增量式迭代获取,对于数据大的数据非常有用,hscan可以实现分片的获取数据,并非一次性将数据全部获取完,从而放置内存被撑爆 # 参数:
# name,redis的name
# cursor,游标(基于游标分批取获取数据)
# match,匹配指定key,默认None 表示所有的key
# count,每次分片最少获取个数,默认None表示采用Redis的默认分片个数 # 如:
# 第一次:cursor1, data1 = r.hscan('xx', cursor=0, match=None, count=None)
# 第二次:cursor2, data1 = r.hscan('xx', cursor=cursor1, match=None, count=None)
# ...
# 直到返回值cursor的值为0时,表示数据已经通过分片获取完毕
10.hscan_iter(name, match=None, count=None)
# 利用yield封装hscan创建生成器,实现分批去redis中获取数据 # 参数:
# match,匹配指定key,默认None 表示所有的key
# count,每次分片最少获取个数,默认None表示采用Redis的默认分片个数 # 如:
# for item in r.hscan_iter('xx'):
# print item
List操作
redis中的List在在内存中按照一个name对应一个List来存储。如图:
1.lpush(name,values)
# 在name对应的list中添加元素,每个新的元素都添加到列表的最左边 # 如:
# r.lpush('oo', 11,22,33)
# 保存顺序为: 33,22,11 # 扩展:
# rpush(name, values) 表示从右向左操作
eg:
r.lpush('fooo',11,22,33)
print(r.lrange('fooo',0,-1)) [b'', b'', b''] Process finished with exit code 0
2.lpushx(name,value)
# 在name对应的list中添加元素,只有name已经存在时,值添加到列表的最左边 # 更多:
# rpushx(name, value) 表示从右向左操作
3.linsert(name, where, refvalue, value))
# 在name对应的列表的某一个值前或后插入一个新值 # 参数:
# name,redis的name
# where,BEFORE或AFTER
# refvalue,标杆值,即:在它前后插入数据
# value,要插入的数据
r.lpush('fooo',11,22,33)
r.linsert('fooo','BEFORE',22,44)
print(r.lrange('fooo',0,-1)) [b'', b'', b'', b'']
4.r.lset(name, index, value)
# 对name对应的list中的某一个索引位置重新赋值 # 参数:
# name,redis的name
# index,list的索引位置
# value,要设置的值
r.lpush('fooo',11,22,33)
print(r.lrange('fooo',0,-1))
r.lset('fooo',0,55)
print(r.lrange('fooo',0,-1)) [b'', b'', b'']
[b'', b'', b''] Process finished with exit code 0
5.r.lrem(name, value, num)
# 在name对应的list中删除指定的值 # 参数:
# name,redis的name
# value,要删除的值
# num, num=0,删除列表中所有的指定值;
# num=2,从前到后,删除2个;
# num=-2,从后向前,删除2个
6.lpop(name)
# 在name对应的列表的左侧获取第一个元素并在列表中移除,返回值则是第一个元素 # 更多:
# rpop(name) 表示从右向左操作
7.lindex(name, index)
在name对应的列表中根据索引获取列表元素
8.ltrim(name, start, end)
在name对应的列表中移除没有在start-end索引之间的值(两边的值)
9.rpoplpush(src, dst)
# 从一个列表取出最右边的元素,同时将其添加至另一个列表的最左边
# 参数:
# src,要取数据的列表的name
# dst,要添加数据的列表的name
10.自定义增量迭代
# 由于redis类库中没有提供对列表元素的增量迭代,如果想要循环name对应的列表的所有元素,那么就需要:
# 1、获取name对应的所有列表
# 2、循环列表
# 但是,如果列表非常大,那么就有可能在第一步时就将程序的内容撑爆,所有有必要自定义一个增量迭代的功能: def list_iter(name):
"""
自定义redis列表增量迭代
:param name: redis中的name,即:迭代name对应的列表
:return: yield 返回 列表元素
"""
list_count = r.llen(name)
for index in xrange(list_count):
yield r.lindex(name, index) # 使用
for item in list_iter('pp'):
print item
Set操作
Set集合就是不允许重复的列表
1.sadd(name,values)
name对应的集合中添加元素
r.sadd('qwe',,,,,,)
print(r.smembers('qwe'))
{b'', b'', b'', b'', b''} Process finished with exit code
2.sdiff(keys, *args)
在第一个name对应的集合中且不在其他name对应的集合的元素集合
3.sdiffstore(dest, keys, *args)
获取第一个name对应的集合中且不在其他name对应的集合,再将其新加入到dest对应的集合中
r.sadd('qwe',1,2,3,4,2,33)
r.sadd('asd',1,2,3,5)
print(r.smembers('qwe'))#输出集合的全部成员
print(r.scard('qwe'))#输出集合的个数
print(r.sdiff('qwe','asd'))#在第一个集合中而不再第二个集合中
print(r.sdiffstore('zxc','qwe','asd'))
print(r.smembers('zxc'))#将在第一个集合中不再第二个集合中的成员存入第三个dest集合
4.sinter(keys, *args)
r.sadd('asd',1,2,3,5)
r.sadd('qwe',1,2,3,4,2,33)
print(r.sinter('qwe','asd'))#取交集即在第一个集合又在第二个集合的成员
5.sinterstore(dest, keys, *args)
将并集存放在目标集合dest中
6.sismember(name, value)
检查成员是否在集合中
7.smove(src, dst, value)
将某个成员从一个集合移动到另一个集合
r.sadd('qwe',1,2,3,4,2,33)
r.sadd('asd',1,2,3,5)
print('qwe-->before',r.smembers('qwe'))
print('asd-->',r.smembers('asd'))
r.smove('qwe','asd',33)
print('qwe-->after',r.smembers('qwe'))
print('asd-->',r.smembers('asd')) qwe-->before {b'', b'', b'', b'', b''}
asd--> {b'', b'', b'', b'', b''}
qwe-->after {b'', b'', b'', b''}
asd--> {b'', b'', b'', b'', b''}
8.spop(name)
从集合的右侧(尾部)移除一个成员,并将其返回
9.srem(name, values)
在name对应的集合中删除某些值
10.sunion(keys, *args)
取两个集合的交集
有序集合
在集合的基础上,为每元素排序;元素的排序需要根据另外一个值来进行比较,所以,对于有序集合,每一个元素有两个值,即:值和分数,分数专门用来做排序。
1.zadd(name, *args, **kwargs)
r.zadd('rty',n1=1,n2=6,n3=5,n4=100)
print(r.zrange('rty',0,-1,withscores=True))
[(b'n1', 1.0), (b'n3', 5.0), (b'n2', 6.0), (b'n4', 100.0)]
Process finished with exit code 0
2.zcard(name)
获取name对应的有序集合元素的数量
3.zcount(name, min, max)
获取name对应的有序集合中分数 在 [min,max] 之间的个数
4.zincrby(name, value, amount)
自增name对应的有序集合的 name 对应的分数
5.r.zrange( name, start, end, desc=False, withscores=False, score_cast_func=float)
# 按照索引范围获取name对应的有序集合的元素 # 参数:
# name,redis的name
# start,有序集合索引起始位置(非分数)
# end,有序集合索引结束位置(非分数)
# desc,排序规则,默认按照分数从小到大排序
# withscores,是否获取元素的分数,默认只获取元素的值
# score_cast_func,对分数进行数据转换的函数 # 更多:
# 从大到小排序
# zrevrange(name, start, end, withscores=False, score_cast_func=float) # 按照分数范围获取name对应的有序集合的元素
# zrangebyscore(name, min, max, start=None, num=None, withscores=False, score_cast_func=float)
# 从大到小排序
# zrevrangebyscore(name, max, min, start=None, num=None, withscores=False, score_cast_func=float)
6.zrank(name, value)
获取某个值在 name对应的有序集合中的排行(从 0 开始)
7.zrangebylex(name, min, max, start=None, num=None)
# 当有序集合的所有成员都具有相同的分值时,有序集合的元素会根据成员的 值 (lexicographical ordering)来进行排序,而这个命令则可以返回给定的有序集合键 key 中, 元素的值介于 min 和 max 之间的成员
# 对集合中的每个成员进行逐个字节的对比(byte-by-byte compare), 并按照从低到高的顺序, 返回排序后的集合成员。 如果两个字符串有一部分内容是相同的话, 那么命令会认为较长的字符串比较短的字符串要大 # 参数:
# name,redis的name
# min,左区间(值)。 + 表示正无限; - 表示负无限; ( 表示开区间; [ 则表示闭区间
# max,右区间(值)
# start,对结果进行分片处理,索引位置
# num,对结果进行分片处理,索引后面的num个元素 # 如:
# ZADD myzset 0 aa 0 ba 0 ca 0 da 0 ea 0 fa 0 ga
# r.zrangebylex('myzset', "-", "[ca") 结果为:['aa', 'ba', 'ca'] # 更多:
# 从大到小排序
# zrevrangebylex(name, max, min, start=None, num=None)
8.zrem(name, values)
删除name对应的有序集合中值是values的成员
9.zremrangebyrank(name, min, max)
根据排行范围删除
zremrangebyscore(name, min, max)
根据分数范围删除
redis应用:收音机
import redis
class Redis_helper(object):
def __init__(self):
self.r = redis.Redis(host='192.168.30.129',port=6379)#连接收音机服务器
self.sub = 'fm97.6'#设定收听和发送方为同一个频段
self.pub = 'fm97.6'
def publish(self,msg):
self.r.publish(self.pub,msg)
return True
def subscribe(self):
pub = self.r.pubsub()#打开收音机
pub.subscribe(self.sub)#拧到想听的台(频段)
pub.parse_response() # 准备接收parse_response()在次调用parse_response() 开始接收
return pub
from Python_redis.redis_helper import Redis_helper
obj = Redis_helper()#实例化类
obj_sub = obj.subscribe()#调用类的订阅方法,订阅fm97.6 while True:
msg = obj_sub.parse_response()#二次调用开始收听
print(msg)
from Python_redis.redis_helper import Redis_helper obj = Redis_helper()#实例化类
obj.publish('Hi!')#调用类的发布方法,发布消息
加油!!!!!
Python 随笔之Redis的更多相关文章
- 安装redis,以及python如何引用redis
下载 cd /usr/local/src/ wget http://download.redis.io/releases/redis-2.8.17.tar.gz 解压 tar -zxvf redis- ...
- redis的安装使用以及在python中操作redis
一.Redis介绍: Redis可以看作是一个key-value的存储系统,它为我们提供了丰富的数据结构,包括lists,sets,ordered sets和hashes.还包括了对这些数据结构的丰富 ...
- Python中的 redis keyspace 通知
介绍 Redis是内存中的数据结构存储,用于缓存.高速数据摄取.处理消息队列.分布式锁定等等. 与其他内存存储相比,使用Redis的优势在于它提供了持久性和数据结构,比如列表.集合.排序集合和散列. ...
- [转]使用python来操作redis用法详解
转自:使用python来操作redis用法详解 class CommRedisBase(): def __init__(self): REDIS_CONF = {} connection_pool = ...
- python3.4学习笔记(二十五) Python 调用mysql redis实例代码
python3.4学习笔记(二十五) Python 调用mysql redis实例代码 #coding: utf-8 __author__ = 'zdz8207' #python2.7 import ...
- python中的Redis键空间通知(过期回调)
介绍 Redis是一个内存数据结构存储库,用于缓存,高速数据摄取,处理消息队列,分布式锁定等等. 使用Redis优于其他内存存储的优点是Redis提供持久性和数据结构,如列表,集合,有序集和散列. 在 ...
- python下操作redis
python安装这里我只介绍如何在Windows上安装redis,以及接下来的实践都是在Windows上进行的.在Windows上安装python的依赖库,常用的方法有两种,第一种是直接通过pip i ...
- python笔记-12 redis缓存
一.redis引入 1.简要概括redis 1.1 redis默认端口:6379 1.2 redis实现的效果:资源共享 1.3 redis实现的基本原理:不同的进程和一个公共的进程之间建立socke ...
- python进阶12 Redis
python进阶12 Redis 一.概念 #redis是一种nosql(not only sql)数据库,他的数据是保存在内存中,同时redis可以定时把内存数据同步到磁盘,即可以将数据持久化,还提 ...
随机推荐
- .Net Core中依赖注入服务使用总结
一.依赖注入 引入依赖注入的目的是为了解耦和.说白了就是面向接口编程,通过调用接口的方法,而不直接实例化对象去调用.这样做的好处就是如果添加了另一个种实现类,不需要修改之前代码,只需要修改注入的地方将 ...
- Reboot
目标是将浏览器的预设样式设为一致 Native font stack 本机字体堆栈 由于padding 及 border 会改变元素在运算后的宽度 此时的实际宽度为: width+左右padding ...
- vue -- 插件的开发与使用
开发插件 插件通常会为 Vue 添加全局功能.插件的范围没有限制--一般有下面几种: 1.添加全局方法或者属性,如: vue-custom-element. 2.添加全局资源:指令/过滤器/过渡等,如 ...
- Codeforces Round #527 (Div. 3)F(DFS,DP)
#include<bits/stdc++.h>using namespace std;const int N=200005;int n,A[N];long long Mx,tot,S[N] ...
- 定时器详解和应用、js加载阻塞、css加载阻塞
1.setTimeout().setInterval()详解和应用 1.1 详解: setTimeout.setInterval执行时机 1.2 存在问题: setInterval重复定时器可能存在的 ...
- jzoj3208. 【JSOI2013】编程作业(kmp)
题面 Description Will相信,很多同学都有过这样的经历:大牛已经写好了编程作业,而作为菜鸟的自己不会写怎么办呢?拿大牛的代码抄一下嘛!但是提交一模一样的作业是不是不太好?于是就改一改变量 ...
- 解读人:闫克强,Metabolic and gut microbial characterization of obesity-prone mice under high-fat diet(高脂饮食下易胖倾向小鼠的代谢和肠道微生物菌群特征分析)
单位: 上海中医药大学 蚌埠医学院 上海交通大学附属第六人民医院 夏威夷大学癌症中心 第二军医大学 技术:非靶向代谢组学,16S rRNA测序技术 一. 概述: 本研究对小鼠进行高脂饮食,根据体重增长 ...
- (四)从输入URL到页面加载发生了什么
一.从输入URL到页面加载发生了什么 1.在浏览器中输入URL 如:https://www.cnblogs.com/loveapple/ URL分成协议.地址.路径三部分 协议:http.https. ...
- thinkphp5加密解密
thinkphp5目前没有提供加密解密类,但是tp3.2中提供了好几种加密解密方法,我们可以吧3.2的这些类拿来使用. 1.将tp3.2中ThinkPHP\Library\Think的Crypt文件夹 ...
- JMeter - 连续性能测试 - JMeter + ANT + Jenkins集成 - 第2部分
目标: 创建包含性能测试流程的持续交付管道,以尽早检测任何与性能相关的问题. 通常,全面的性能测试将在分段/预生产环境中完成,该环境可能与您的生产环境相同.在完成QA功能/回归验证后,将代码推送到分段 ...