Python操作Redis的最佳实践

文章转自:http://blog.51cto.com/steed/2057706

目录

  • 安装

  • redis 模块

  • Redis API 使用

  • 连接方式

  • String 操作

  • 按位操作的应用场景

  • Hash 操作

  • scan方法-用于获取大量的数据

  • List 操作

  • 阻塞的pop方法

  • Set 集合操作

  • 有序集合

  • 关于db

  • 管道

  • 发布/订阅

Redis-缓存系统

缓存系统也可以叫缓存数据库,现在主流的系统有 Redis 和 Memcached :
MongoDB,比较早的缓存系统,直接持久化到硬盘
Redis,现在正火的。半持久化数据,数据默认存在内存中,可以持久化到硬盘里持久保存。效率高,在单线程下运行,通过epoll实现的高并发
Memcached,轻量级的缓存系统,不能持久化只能存在内存中。相对应该比较简单,可以自学?

1、安装

通过yum安装就好了,在epel源里:

$ yum install redis

开放防火墙:

$ firewall-cmd --permanent --add-port=6379/tcp$ firewall-cmd --reload

开启服务:

$ redis-server

可以在命令后面加上 & ,这样启动后就是运行在后台。如果再后台运行想停止服务:

$ redis-cli shutdown

另外,redis默认是以保护模式启动的,只能本机连。你的redis可能不是运行在本机的,比如在虚拟机上,那么本机以外可能连不上,或者只能连不能改。就不要那么麻烦再去整配置文件了,这里以学习测试为主。

推荐这么启动:

$ redis-server --protected-mode no

你也可以根据需要加上 & 启动后再后台运行。配置文件什么的用的时候再去研究吧,这里我们搭建学习环境。
可以先进入redis的命令行界面里简单操作一下,进入命令行界面:

$ redis-cli

简单的存一个值:

> set age 23

age是key,23是value,取出age的值:

> get age

查看已经存了哪些key:

> keys *

存值,有存活时间:

> set city ShangHai ex 2

上面存的值只能存活2秒,超过时间再去get,返回的就是(nil)
帮助命令很有用,有不清楚的,可以看下命令的语法和说明

> help [ 命令 ]


2、redis 模块

使用python操作redis,需要安装第三方模块,模块名也叫redis。

3、Redis API 使用

redis-py 的API的使用可以分类为:

  • 连接方式

    • 连接

    • 连接池

  • 操作

    • String 操作

    • Hash 操作

    • List 操作

    • Set 操作

    • Sort Set 操作

  • 管道

  • 发布订阅

参考资料:
https://github.com/andymccurdy/redis-py/
Redis 命令参考(中文翻译版):

http://doc.redisfans.com/

4、连接方式

先来连接redis,然后把上面命令行界面里的操作在python上再做一遍:

Python操作Redis的最佳实践_第1张图片

上面注释的部分给了另外一种通过连接池连接的方式,使用的时候,推荐使用连接池连接:
redis-py使用connection pool来管理对一个redis server的所有连接,避免每次建立、释放连接的开销。默认每个Redis实例都会维护一个自己的连接池。可以直接建立一个连接池,然后作为参数Redis,这样就可以实现多个Redis实例共享一个连接池。

5、String 操作

redis中的String在内存中是按照一个key对应一个value来存储。
set(name, value, ex=None, px=None, nx=False, xx=False) :设置值,默认如果key不存在则创建,key存在则修改
可选参数:

  • ex :过期时间(秒)

  • px :过期时间(毫秒)

  • nx :若设为True,只有name不存在时,set操作才执行

  • xx :若设为True,只有name存在时,set操作才执行

setnx(name, value) :效果同上面的 ns=True
setex(name, value, time) :效果同上面的 ex=time
psetex(name, time_ms, value) :效果同上面的 px=time_ms
get(name) :获取值

mset(*args, **kwargs) :批量设置
mget(keys, *args) :批量获取

Python操作Redis的最佳实践_第2张图片

getset(name, value) 获取name的当前值,然后给name赋一个新的值

Python操作Redis的最佳实践_第3张图片

getrange(key, start, end) :获取子序列,相当于列表切片(字符串也可以当列表操作)

Python操作Redis的最佳实践_第4张图片

setrange(name, offset, value) :修改字符串内容,从指定字符串索引开始向后替换(新值太长时,则向后添加)

Python操作Redis的最佳实践_第5张图片

setbit(name, offset, value) :修改字符串内容,这里按二进制的bit位进行操作。上面那个是按字节操作

Python操作Redis的最佳实践_第6张图片

getbit(name, offset) :获取name对应的值的二进制表示中的那一位的值,不是0就是1
bitcount(key, start=None, end=None) :获取name对应的值的二进制表中 1 的个数,加上 start 和 end 参数限制统计的范围

6、按位操作的应用场景

用最省空间的方式,存储在线用户数及分别是哪些用户在线。
用户状态只有2种,0离线,1在线。每个用户的状态只占1个位,每个用户都有一个用户id,用户id就是这个用户状态存储在变量中的 offset 的位置,具体看代码示例:

Python操作Redis的最佳实践_第7张图片

bitop(operation, dest, *keys) :获取keys的值,按照operation的方法做位运算,结果赋值给dest。用不到

strlen(name) :返回name对应值的字节长度(一个汉字3个字节)
incr(name, amount=1) :自增 name 对应的值,当 name 不存在时,则创建 name=amount
decr(name, amount=1) :自减 name 对应的值,当 name 不存在时,则创建 name=amount
incrbyfloat(name, amount=1.0) :和上面差不多,支持浮点型数值

Python操作Redis的最佳实践_第8张图片

append(key, value) :在 key 的 value 值后面追加内容

Python操作Redis的最佳实践_第9张图片


7、Hash 操作

hash表现形式上有些像pyhton中的dict,可以存储一组关联性较强的数据
hset(name, key, value) :在name对应的hash中设置一个键值对(不存在,则创建;否则,修改)
hmset(name, mapping) :在name对应的hash中批量设置键值对
hget(name, key) :在name对应的hash中根据key获取value
hmget(name, keys, *args) :在name对应的hash中获取多个key的值
hgetall(name) :获取name对应hash的所有键值,key 和 value都获取,但是无区分

hlen(name) :获取name对应的hash中键值对的个数
hkeys(name) :获取name对应的hash中所有的key的值
hvals(name) :获取name对应的hash中所有的value的值
hexists(name, key) :检查name对应的hash是否存在当前传入的key

Python操作Redis的最佳实践_第10张图片

hdel(name,*keys) :将name对应的hash中指定key的键值对删除
hincrby(name, key, amount=1) :自增name对应的hash中的指定key的值,不存在则创建key=amount
hincrbyfloat(name, key, amount=1.0) :自增name对应的hash中的指定key的值,不存在则创建key=amount

8、scan方法-用于获取大量的数据

hscan(name, cursor=0, match=None, count=None) :增量式迭代获取,对于获取数据量很大的数据时非常有用,hscan可以实现分片的获取数据,并非一次性将数据全部获取完,从而防止内存被撑爆。参数:

  • name :redis的name

  • cursor :游标(基于游标分批取获取数据)

  • match :匹配指定key,默认None表示所有的key。可以用通配符,? * 等,具体参考其他常用操作中的 keys 命令的参数

  • count :每次分片最少获取个数,默认None表示采用Redis的默认分片个数

hscan_iter(name, match=None, count=None) :利用yield封装hscan创建生成器,实现分批去redis中获取数据

9、List 操作

redis中的List在在内存中是按照一个name对应一个List来存储。
lpush(name,values) :在name对应的list中添加元素,每个新的元素都添加到列表的最左边
rpush(name,values) :同上,添加到右边
llen(name) :name对应的list元素的个数
lrange(name, start, end) :在name对应的列表分片获取数据,要获取列表全部,就 0, -1

Python操作Redis的最佳实践_第11张图片

lpushx(name,value) :在name对应的list中添加元素,只有name已经存在时,值添加到列表的最左边
rpushx(name,value) :同上,添加到右边

Python操作Redis的最佳实践_第12张图片

linsert(name, where, refvalue, value)) :在name对应的列表的某一个值前(‘before’)或后(‘after’)插入一个新值

Python操作Redis的最佳实践_第13张图片

r.lset(name, index, value) :对name对应的list中的某一个索引位置重新赋值

Python操作Redis的最佳实践_第14张图片

r.lrem(name, value, num) :在name对应的list中删除指定的值。num为0删除所有;num为正数,从前往后删除num个;num为负数,从后向前删除num个。

Python操作Redis的最佳实践_第15张图片

lpop(name) :在name对应的列表的左侧获取第一个元素并在列表中移除,返回值则是第一个元素
rpop(name) :同上,从右侧获取并移除
lindex(name, index) :使用下标获取值
ltrim(name, start, end) :移除 start 和 end索引位置以外的值

Python操作Redis的最佳实践_第16张图片

rpoplpush(src, dst) :从一个列表取出最右边的元素,同时将其添加至另一个列表的最左边

Python操作Redis的最佳实践_第17张图片


10、阻塞的pop方法

下面的2个pop方法和前面不带b开头的方法基本上是一样的,但是多了一个timeout参数。在timeout的时间内如果列表中没有值,则阻塞,一旦有值进来,就会取出来。非常像队列的操作。timeout如果是0,则一直阻塞,直到取到值。如果timeout时间到还没取到值,会返回None。
blpop(keys, timeout) :将多个列表排列,按照从左到右去pop对应列表的元素。这里keys可以是多个name
brpop(keys, timeout) :同上,每个列表中取元素的时候是从右开始
brpoplpush(src, dst, timeout=0) :
blpop 和 brpop 和前面略有不同,可以从多个列表中取值,具体效果如下:

Python操作Redis的最佳实践_第18张图片


11、Set 集合操作

Set集合就是不允许重复的列表,并且集合是无序的。后面有有序集合
sadd(name,values) :name对应的集合中添加元素
scard(name) :获取name对应的集合中元素个数
smembers(name) :获取name对应的集合的所有成员

Python操作Redis的最佳实践_第19张图片

sdiff(keys, *args) :差集,返回一个集合
sdiffstore(dest, keys, *args) :同上,返回值是新集合的元素个数,新集合存储到dest中
sinter(keys, *args) :交集,返回一个集合
sinterstore(dest, keys, *args) :同上,返回值是新集合的元素个数,新集合存储到dest中
sunion(keys, *args) :并集,返回一个集合
sunionstore(dest,keys, *args) :同上,返回值是新集合的元素个数,新集合存储到dest中

Python操作Redis的最佳实践_第20张图片

sismember(name, value) :values 是否是 name 集合的成员
smove(src, dst, value) :将某个成员从一个集合中移动到另外一个集合
spop(name) :从集合的右侧(尾部)移除一个成员,并将其返回
srandmember(name, numbers) :从name对应的集合中随机获取 numbers 个元素,默认就取1个,可以取多个。
srem(name, values) :在name对应的集合中删除某些值

Python操作Redis的最佳实践_第21张图片

同之前 Hash 操作中的 scan 方法相似,用于获取大量数据的方法
sscan(name, cursor=0, match=None, count=None)
sscan_iter(name, match=None, count=None)


12、有序集合

有序集合,在集合的基础上,为每个元素排序,元素的排序需要根据另外一个值来进行比较。所以,对于有序集合,每一个元素有两个值,即:值和分数,分数专门用来做排序。


zadd(name, *args, **kwargs) :在name对应的有序集合中添加元素,每个成员都要有一个分数,2种可是可选,看例子
zcard(name) :获取name对应的有序集合元素的数量
zcount(name, min, max) :也是统计集合的元素数量,但是是满足分数在 min 和 max 之间的元素的数量

Python操作Redis的最佳实践_第22张图片

zincrby(name, value, amount) :自增name对应的有序集合的 value 对应的分数,默认自增1
r.zrange( name, start, end, desc=False, withscores=False, score_cast_func=float) :按照索引范围获取有序集合的元素
参数:

  • name :

  • start :有序集合索引起始位置(非分数)

  • end :有序集合索引结束位置(非分数)

  • desc :排序规则,默认按照分数从小到大排序

  • withscores :是否获取元素的分数,默认只获取元素的值

  • score_cast_func :对分数进行数据转换的函数

r.zrevrange( name, start, end, withscores=False, score_cast_func=float) :另一种从大到小排列的方法

Python操作Redis的最佳实践_第23张图片

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) :同上,从大到小

Python操作Redis的最佳实践_第24张图片

r.zrangebylex(name, min, max, start=None,num=None) :跳过,没讲,不好理解还用不上
r.zrevrangebylex(name, max, min, start=None,num=None) :同上,从打到小排列
r.zremrangebylex(name, min, max) :跳过

zrank(name, value) :获取某个值在 name 对应的有序集合中的排行(从 0 开始)。可以做班级成绩的排名
zrem(name, values) :删除name对应的有序集合中值是values的成员,删除单个或多个成员
zremrangebyrank(name, min, max) :根据排行范围删除
zremrangebyscore(name, min, max) :根据分数范围删除
zscore(name, value) :获取name对应有序集合中 value 对应的分数

Python操作Redis的最佳实践_第25张图片

zinterstore(dest, keys, aggregate=None) :获取两个有序集合的交集,如果遇到相同值不同分数,则按照aggregate进行操作
zunionstore(dest, keys, aggregate=None) :获取两个有序集合的并集,如果遇到相同值不同分数,则按照aggregate进行操作
aggregate的值为: SUM MIN MAX

Python操作Redis的最佳实践_第26张图片

同之前 Hash 操作中的 scan 方法相似,用于获取大量数据的方法
zscan(name, cursor=0, match=None, count=None, score_cast_func=float)
zscan_iter(name, match=None, count=None,score_cast_func=float)

其他常用操作

delete(*names) :根据删除redis中的任意数据类型
flushdb() :删除当前db的所有数据
flushall() :删除所有db的所有数据
exists(name) :检测redis的name是否存在
keys(pattern='*') :根据模型获取redis的name,pattem参数可以使用通配符匹配,参考如下:

  • KEYS * 匹配数据库中所有 key

  • KEYS h?llo 匹配 hello , hallo 和 hxllo 等

  • KEYS h*llo 匹配 hllo 和 heeeeello 等

  • KEYS h[ae]llo 匹配 hello 和 hallo ,但不匹配 hillo

expire(name ,time) :为name设置超时时间。这个方法可以不必在赋值的时候就设置时间了,而且还能用于更新时间
rename(src, dst) :为name重命名
move(name, db)) :将name移动到另外一个db中

13、关于db

db就是数据库,当 redis 服务器初始化时,会预先分配 16 (0-15)个数据库(该数量可以通过配置文件配置)。
之前的操作都是在默认的db=0下操作的。
cli命令行界面下,使用select命令切换库。python中可以在建立连接的时候声明连接哪个库。


删除数据和db的操作:

Python操作Redis的最佳实践_第27张图片

移动、重命名:

Python操作Redis的最佳实践_第28张图片

randomkey() :随机获取一个redis的name(不删除)
type(name) :获取name对应值的类型

同之前 Hash 操作中的 scan 方法相似,用于获取大量数据的方法:
scan(cursor=0, match=None, count=None)
scan_iter(match=None, count=None)

14、管道

redis-py默认在执行每次请求都会创建(连接池申请连接)和断开(归还连接池)一次连接操作,如果想要在一次请求中指定多个命令,则可以使用pipline实现一次请求指定多个命令,并且默认情况下一次 pipline 是原子性操作。

Python操作Redis的最佳实践_第29张图片


15、发布/订阅

这里分消息的发布方和订阅方。
发布消息,建立连接,然后发布消息。每条消息都有消息的频道和内容。
订阅消息,建立连接,订阅频道。开始接收消息。
发布方:

Python操作Redis的最佳实践_第30张图片

订阅方:

Python操作Redis的最佳实践_第31张图片

感觉这里以及上面的部分功能(List 操作中阻塞的pop方法)和消息队列有交集,需要的时候选择是个更加合适的系统使用。
这里讲的比较简单,基本上就是简单过了一遍。还有更多细致的功能,只能去查阅文档资料了。

在Python开发中经常会使用到Redis做缓存、消息队列等业务场景,此文全方面说明了Redis用法,建议收藏,以备后用!

--完--

如果需要Redis视频,可以在公众号后台聊天框回复【Redis视频】,可以免费获取编程视频 。

Redis其它推荐阅读:

Redis 零基础入门视频教程

Linux 安装 Redis 图文教程

刚接触学Redis,看这一篇就够了!

再来聊聊Redis到底是什么?

说说 Redis 数据结构和常用命令

Redis最常见面试问题,附答案!

Redis的字符串是怎么实现的?

阿里巴巴官方 Redis 开发规范!

如何借助 Redis 实现秒杀系统?

如何用Redis实现微博关注关系?

史上最全Redis总结,干货满满!

史上最全 Redis 高可用解决方案总结

如何借助 Redis 实现实现排行榜功能?

10 个正确使用 Redis 的技巧

Redis 分布式锁的正确实现方式

Redis 源码学习之 Redis 事务

详解Redis的内存淘汰策略

Redis 的各项功能,都解决了哪些问题?

为什么单线程的Redis却能支撑高并发?

Redis应用场景,实现功能 “附近的人”

超详细揭秘 Redis 持久化,建议收藏!

详解 Redis AOF 持久化

Redis RDB 持久化详解

后端开发都应该掌握的Redis基础

Redis是如何实现点赞、取消点赞的?

Redis实践:网站搜索的热搜词

如何用 Redis 做实时订阅推送的?

Redis 主从复制以及主从复制原理

如何访问 Redis 中的海量数据?

一文深入了解Redis内存模型!

Redis 导致应用卡死 bug 全过程

Redis常见的几种缓存模式

玩转Redis集群的搭建、命令

一个基于 Redis 的限流系统的设计!

长按加入10W+朋友的IT圈

觉得内容还不错的话,给我点个“在看”呗

你可能感兴趣的:(数据库,python,redis,java,编程语言)