文章转自:http://blog.51cto.com/steed/2057706
目录
安装
redis 模块
Redis API 使用
连接方式
String 操作
按位操作的应用场景
Hash 操作
scan方法-用于获取大量的数据
List 操作
阻塞的pop方法
Set 集合操作
有序集合
关于db
管道
发布/订阅
缓存系统也可以叫缓存数据库,现在主流的系统有 Redis 和 Memcached :
MongoDB,比较早的缓存系统,直接持久化到硬盘
Redis,现在正火的。半持久化数据,数据默认存在内存中,可以持久化到硬盘里持久保存。效率高,在单线程下运行,通过epoll实现的高并发
Memcached,轻量级的缓存系统,不能持久化只能存在内存中。相对应该比较简单,可以自学?
通过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 [ 命令 ]
使用python操作redis,需要安装第三方模块,模块名也叫redis。
redis-py 的API的使用可以分类为:
连接方式
连接
连接池
操作
String 操作
Hash 操作
List 操作
Set 操作
Sort Set 操作
管道
发布订阅
参考资料:
https://github.com/andymccurdy/redis-py/
Redis 命令参考(中文翻译版):
http://doc.redisfans.com/
先来连接redis,然后把上面命令行界面里的操作在python上再做一遍:
上面注释的部分给了另外一种通过连接池连接的方式,使用的时候,推荐使用连接池连接:
redis-py使用connection pool来管理对一个redis server的所有连接,避免每次建立、释放连接的开销。默认每个Redis实例都会维护一个自己的连接池。可以直接建立一个连接池,然后作为参数Redis,这样就可以实现多个Redis实例共享一个连接池。
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=Truesetex(name, value, time)
:效果同上面的 ex=timepsetex(name, time_ms, value)
:效果同上面的 px=time_msget(name)
:获取值
mset(*args, **kwargs)
:批量设置mget(keys, *args)
:批量获取
getset(name, value)
获取name的当前值,然后给name赋一个新的值
getrange(key, start, end)
:获取子序列,相当于列表切片(字符串也可以当列表操作)
setrange(name, offset, value)
:修改字符串内容,从指定字符串索引开始向后替换(新值太长时,则向后添加)
setbit(name, offset, value)
:修改字符串内容,这里按二进制的bit位进行操作。上面那个是按字节操作
getbit(name, offset)
:获取name对应的值的二进制表示中的那一位的值,不是0就是1bitcount(key, start=None, end=None)
:获取name对应的值的二进制表中 1 的个数,加上 start 和 end 参数限制统计的范围
用最省空间的方式,存储在线用户数及分别是哪些用户在线。
用户状态只有2种,0离线,1在线。每个用户的状态只占1个位,每个用户都有一个用户id,用户id就是这个用户状态存储在变量中的 offset 的位置,具体看代码示例:
bitop(operation, dest, *keys)
:获取keys的值,按照operation的方法做位运算,结果赋值给dest。用不到
strlen(name)
:返回name对应值的字节长度(一个汉字3个字节)incr(name, amount=1)
:自增 name 对应的值,当 name 不存在时,则创建 name=amountdecr(name, amount=1)
:自减 name 对应的值,当 name 不存在时,则创建 name=amountincrbyfloat(name, amount=1.0)
:和上面差不多,支持浮点型数值
append(key, value)
:在 key 的 value 值后面追加内容
hash表现形式上有些像pyhton中的dict,可以存储一组关联性较强的数据hset(name, key, value)
:在name对应的hash中设置一个键值对(不存在,则创建;否则,修改)hmset(name, mapping)
:在name对应的hash中批量设置键值对hget(name, key)
:在name对应的hash中根据key获取valuehmget(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
hdel(name,*keys)
:将name对应的hash中指定key的键值对删除hincrby(name, key, amount=1)
:自增name对应的hash中的指定key的值,不存在则创建key=amounthincrbyfloat(name, key, amount=1.0)
:自增name对应的hash中的指定key的值,不存在则创建key=amount
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中获取数据
redis中的List在在内存中是按照一个name对应一个List来存储。lpush(name,values)
:在name对应的list中添加元素,每个新的元素都添加到列表的最左边rpush(name,values)
:同上,添加到右边llen(name)
:name对应的list元素的个数lrange(name, start, end)
:在name对应的列表分片获取数据,要获取列表全部,就 0, -1
lpushx(name,value)
:在name对应的list中添加元素,只有name已经存在时,值添加到列表的最左边rpushx(name,value)
:同上,添加到右边
linsert(name, where, refvalue, value))
:在name对应的列表的某一个值前(‘before’)或后(‘after’)插入一个新值
r.lset(name, index, value)
:对name对应的list中的某一个索引位置重新赋值
r.lrem(name, value, num)
:在name对应的list中删除指定的值。num为0删除所有;num为正数,从前往后删除num个;num为负数,从后向前删除num个。
lpop(name)
:在name对应的列表的左侧获取第一个元素并在列表中移除,返回值则是第一个元素rpop(name)
:同上,从右侧获取并移除lindex(name, index)
:使用下标获取值ltrim(name, start, end)
:移除 start 和 end索引位置以外的值
rpoplpush(src, dst)
:从一个列表取出最右边的元素,同时将其添加至另一个列表的最左边
下面的2个pop方法和前面不带b开头的方法基本上是一样的,但是多了一个timeout参数。在timeout的时间内如果列表中没有值,则阻塞,一旦有值进来,就会取出来。非常像队列的操作。timeout如果是0,则一直阻塞,直到取到值。如果timeout时间到还没取到值,会返回None。blpop(keys, timeout)
:将多个列表排列,按照从左到右去pop对应列表的元素。这里keys可以是多个namebrpop(keys, timeout)
:同上,每个列表中取元素的时候是从右开始brpoplpush(src, dst, timeout=0)
:
blpop 和 brpop 和前面略有不同,可以从多个列表中取值,具体效果如下:
Set集合就是不允许重复的列表,并且集合是无序的。后面有有序集合sadd(name,values)
:name对应的集合中添加元素scard(name)
:获取name对应的集合中元素个数smembers(name)
:获取name对应的集合的所有成员
sdiff(keys, *args)
:差集,返回一个集合sdiffstore(dest, keys, *args)
:同上,返回值是新集合的元素个数,新集合存储到dest中sinter(keys, *args)
:交集,返回一个集合sinterstore(dest, keys, *args)
:同上,返回值是新集合的元素个数,新集合存储到dest中sunion(keys, *args)
:并集,返回一个集合sunionstore(dest,keys, *args)
:同上,返回值是新集合的元素个数,新集合存储到dest中
sismember(name, value)
:values 是否是 name 集合的成员smove(src, dst, value)
:将某个成员从一个集合中移动到另外一个集合spop(name)
:从集合的右侧(尾部)移除一个成员,并将其返回srandmember(name, numbers)
:从name对应的集合中随机获取 numbers 个元素,默认就取1个,可以取多个。srem(name, values)
:在name对应的集合中删除某些值
同之前 Hash 操作中的 scan 方法相似,用于获取大量数据的方法sscan(name, cursor=0, match=None, count=None)
sscan_iter(name, match=None, count=None)
有序集合,在集合的基础上,为每个元素排序,元素的排序需要根据另外一个值来进行比较。所以,对于有序集合,每一个元素有两个值,即:值和分数,分数专门用来做排序。
zadd(name, *args, **kwargs)
:在name对应的有序集合中添加元素,每个成员都要有一个分数,2种可是可选,看例子zcard(name)
:获取name对应的有序集合元素的数量zcount(name, min, max)
:也是统计集合的元素数量,但是是满足分数在 min 和 max 之间的元素的数量
zincrby(name, value, amount)
:自增name对应的有序集合的 value 对应的分数,默认自增1r.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)
:另一种从大到小排列的方法
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)
:同上,从大到小
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 对应的分数
zinterstore(dest, keys, aggregate=None)
:获取两个有序集合的交集,如果遇到相同值不同分数,则按照aggregate进行操作zunionstore(dest, keys, aggregate=None)
:获取两个有序集合的并集,如果遇到相同值不同分数,则按照aggregate进行操作
aggregate的值为: SUM MIN MAX
同之前 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中
db就是数据库,当 redis 服务器初始化时,会预先分配 16 (0-15)个数据库(该数量可以通过配置文件配置)。
之前的操作都是在默认的db=0下操作的。
cli命令行界面下,使用select命令切换库。python中可以在建立连接的时候声明连接哪个库。
删除数据和db的操作:
移动、重命名:
randomkey()
:随机获取一个redis的name(不删除)type(name)
:获取name对应值的类型
同之前 Hash 操作中的 scan 方法相似,用于获取大量数据的方法:scan(cursor=0, match=None, count=None)
scan_iter(match=None, count=None)
redis-py默认在执行每次请求都会创建(连接池申请连接)和断开(归还连接池)一次连接操作,如果想要在一次请求中指定多个命令,则可以使用pipline实现一次请求指定多个命令,并且默认情况下一次 pipline 是原子性操作。
这里分消息的发布方和订阅方。
发布消息,建立连接,然后发布消息。每条消息都有消息的频道和内容。
订阅消息,建立连接,订阅频道。开始接收消息。
发布方:
订阅方:
感觉这里以及上面的部分功能(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圈
觉得内容还不错的话,给我点个“在看”呗