Redis的一些基本操作 - downtiser/python-one GitHub Wiki
Redis是一个高效的key-value型的数据库,它将数据缓存在内存中。现在在Linux上使用redis.有以下一些基本使用方法:
- redis-cli 启动redis客户端
- set key value 设置键值对 跟上ex参数指定其生存时间 如set name downtiser ex 3 这个键值对只在3秒内存在
- keys * 查看现在有哪些key
- get key 获取指定key的value
python 使用redis要先pip redis模块. 为了能在windows上通过pycharm连接redis,需要修改redis的配置文件,将bind 127.0.0.1一行注释掉,再将protectedmode设置为no,在将requirepass一行取消注释,并设置数据库密码,保存后重启redis即可
python简单连接数据库:
#Downtiser
import redis
r = redis.Redis(host='192.168.10.30', port=6379,db=0,password='gu996080') #设置主机ip,端口号和数据库及其密码
r.set('name','noob')
print(r.get('name').decode())
如果需要频繁连接到数据库,可以设置连接池,避免频繁连接:
#Downtiser
import redis
pool = redis.ConnectionPool(host='192.168.10.30', port=6379,db=0,password='gu996080')
r = redis.Redis(connection_pool=pool)
r.set('name','noob')
print(r.get('name').decode())
redis的几种group及其在命令行的操作:
- help 操作名 可以查看操作的格式和说明
- string 及其操作:
- set的几个参数:
- ex:过期时间,s
- px:过期时间,ms
- nx: 默认为False,若为Ture,只有指定的key不存在时set的value才会生效
- xx: 默认为False,若为Ture, 只有指定的key存在时set才会生效
- setnx:就是set的nx参数为Ture
- setex:相当于set加上参数ex SETEX key seconds value
- psetex: 相当于set加上参数px
- mset: 批量设置 MSET key value [key value ...]
- getset: 获取原来key的值并设置新值
- getrange: 类似于字符串切片 getrange key 开始位置 末位置 注意 一个汉字占3个字节
- setrange: 将指定key的value的指定开始位置起往后的一定字符替换为指定字符, 例如
setrange name 2 noob
(原name是downtiser),再get name
得到donoobser
- setbit: 将某个key对应的value的二进制形式的指定位的二进制值修改为1或0,例如
name
的值是D
,对应Ascii吗为68,转换为二进制格式为01000100,所以setbit name 7 1
即将01000100的末位设为1,对应Ascii码变为69,即E,所以再get
name的值就变为了E。另外,设置的位不局限与该字符串,可以是任意位数,例如set name 10000 1
也是可操作的 - bitcount: 统计一个value的二进制形式中位值为1的位的个数,例如
BITCOUNT n
n的值为D,结果返回2 - getbit: 获取一个value二进制格式的指定位的值
getbit n 5
(n=D) 返回1-
将setbit
,bitcount
,getbit
组合可以使数据库实现一些很高效的功能,例如,当一个网络公司的数据库中存放着几亿用户的数据时,如果想要知道用户在线数和是哪些用户在线,可以设置一个key,每有一个用户登录,就根据用户ID设置这个key的对应位为1,例如,用户6080上线,就将key的6080位设置为1:setbit key 6080 1
,所以要统计在线人数只要bitcount key
即可,要知道某个用户是否在线,只要getbit 用户ID
,若值为1,则证明用户在线,这样若要记录上亿用户的登录信息,只要花费几十MB的空间存储key,效率很高
-
- incr:每次用这个命令调用一个key, 对应key的整数值加一, 例如
incr count
,count
的原有值就会加一 - decr:和incr类似,只不过值减一,
- incrbyfloat:
incrbyfloat key 浮点值
,给一个key增加指定的浮点值(可以是负数) - append:
append key value
,在一个key的原value后追加一个新value
- set的几个参数:
- hash 操作:设置一个类似于字典的key,在这个key中还能存储键值对:
- hset:
hset dict name downtiser
,就是在dict这个hash出的类字典存入键值对name downtiser
,在一个类字典中可以存很多键值对 - hgetall:
hgetall dict
,获取一个hash中的所有键与值 - hget:
hget dict name
,获取一个hash中某一个key的value - hkeys:
hkeys dict
,获取一个hash中的所有key - hvals:
hvals
,获取一个hash中的所有value - hmset:
hmset dict k1 1 k2 2
,批量往一个hash中存入键值对 - hmget:
hmget dict k1 k2
批量获取键的值 - hexists:
hexists dict k3
判断一个hash中是否存在指定的key - hdel:
hdel dict name
删除一个hash中指定的键与值 - hincrby:
hincrby dict k1 -1
使一个hash中指定key的value增加指定整数 - hincrbyfloat:和上一条类似,只不过可以加整数
- hscan:
hscan dict 0 match n*
代表从一个hash的开始位置开始检索符合match匹配条件的key并返回键值对
- hset:
- list操作:
- lpush:
lpush name_list downtiser noob idiot
往一个列表中加入值,而且是FILO模式,先放入的值后取出,即从左边放入列表 - rpush: 和lpush类似,只不过先放入的值先取出,就是正常的列表
- lrange:
lrange name_list 1 -1
查询一个列表指定范围内的值 - lpushx:只有当指定列表存在时才放入值
- linsert:
LINSERT name_list before noob pig
往一个列表中某个值的前或后插入一个新值,此代码表示往noob前插入pig - lset:
lset name_list 2 NOOB
将一个列表指定下标的值改为指定值 - lrem:
lrem name_list 1 pig
从左到右将指定个数个指定值删去 - lpop:
lrem name_list
移除指定列表的左边第一个值并返回 - rpop:和上一条类似,只不过移除右边第一个值
- lindex:
lindex name_list 1
获取一个列表中指定下标的值 - ltrim:
ltrim name_list 2 3
移除除指定下标范围内的以外的值 - rpoplpush:
rpoplpush name_list1 name_list2
将第一个列表最右边的值移除并添加到另一个列表的最左边 - blpop:
blpop name_list 阻塞时间
将列表左边元素移除并返回,若没有了就阻塞指定时间,等待新值加入 - brpoplpush:
brpoplpush namelist name_list2 阻塞时间
将第一个列表最右边值移除并添加到另一个列表的最左边
- lpush:
- set操作:其实就是集合
- sadd:
sadd set1 noob
往指定集合中添加成员 - scard:
scard set1
获取指定集合中成员的个数 - smembers:
smembers set1
获取指定集合中所有成员 - sdiff:
sdiff set set1
比较几个集合,获取他们的差集,即不同的元素 - sdiffstore:
sdiffstore set2 set set1
第一个集合存储后面集合的差集 - sinter:
sinter set set1
获取两个集合的交集并返回 - sinterstore:
sinterstore set3 set set1
第一个集合存储后面集合的交集 - sismember:
sismember set1 downtiser
返回一个集合中指定成员的个数 - smove:
smove set set1 要移动的成员
将一个成员从一个集合移动到另一个集合 - srandmember:
srandmember set 2
随机获取一个集合中的指定个数成员 - sremv:
sremv set noob
移除集合中的指定值 - sunion:
sunion set set1
获取几个集合的并集 - sunionstore:同前几个store
- sscan:
SSCAN set 0 match *o*
查找指定集合中所有中间含有o的成员
- sadd:
- 有序集合z:每个值对应一个score,score越低,权值越高,就排在越前面
- zadd:
zadd z1 10 downtiser 8 noob 5 idiot 2 pig
往一个集合中添加value,并根据输入的score排序,score必须是数字,如果value已经存在,则会根据输入的score重新排序 - zcard;
zcard z1
统计集合中值的个数 - zrange:
zrange z1 0 -1
获取指定集合中指定下标范围内的值,如果在末尾加上withscores参数,则会一起返回score - zcount:
zcount z1 5 8
统计集合中指定分数范围内的value的个数 - zincrby:
zincrby z1 downtiser -8
让某个集合中的指定value的score增加指定值 - zrank:
zrank z1 downtiser
获取某个值依据其score在集合中的排名 - zscore:
zscore z1 downtiser
获取某个值的分数 - zremrangebyrank:
zremrangebyrank z1 2 4
移除指定集合内指定排名范围内的值 - zremrangebyscore:
zremrangebyscore z1 5 9
移除指定集合内指定分数范围内的值 - zinterstore:
zinterstore z3 2 z1 z2
获取指定个数个集合的交集,并将交集的value的在原集合的score相加,在放入值z3指定集合中 - zunionstore: 跟上一条类似,只不过是取并集
- zscan:跟列表的类似
- zadd:
- 其他常用操作:
- del:'del key'从数据库中删除指定key(可多个)
- exists:
exists key
检查指定的key是否存在 - expire:
expire key 失效时间
指定在多少时间后该key失效 - rename:
rename oldkey newkey
将指定key重命名为新的key - move:
move key db_id
将某个key移动到指定的数据库下,如果目标数据库已有该key,就不移动,redis默认有编号为0-15的数据库,可以通过修改配置文件更改 - select:
select db_id
进入指定数据库 - type:
type set
查看指定key的类型
- 管道:redis-py默认在执行每次请求都会创建(连接池申请连接)和断开(归还连接池)一次连接操作,如果想要在一次请求中指定多个命令,则可以使用pipline实现一次请求指定多个命令,并且默认情况下一次pipline 是原子性操作。
#Downtiser
import redis, time
pool = redis.ConnectionPool(host='192.168.10.30', port=6379,db=3,password='gu996080')
r = redis.Redis(connection_pool=pool)
pipe = r.pipeline(transaction=True) #设置管道,True则自动执行命令
pipe.set('name','downtiser')
time.sleep(15) #此时去数据库中查找,name是空的
pipe.set('age',20)
pipe.execute()#一次性执行任务,再去查找,两个key都有值了
- 用redis实现和RabbitMQ类似的发布与订阅的功能:
- 首先先对发布方和订阅方进行类封装:
#Downtiser
import redis
class redis_handler(object):
def __init__(self):
self.__conn = redis.Redis('192.168.10.30', db=2, password='gu996080') #连接数据库
self.pub_channel = '168.5' #指明发送消息的通道
self.sub_channel = '168.5'
def pub(self, message_from_publisher):
self.__conn.publish(self.pub_channel, message_from_publisher) #指明发布消息的通道和要发送的消息
def sub(self):
pub = self.__conn.pubsub() #生成发布/订阅实例,通过这个实例,可以收听指定频道并接受消息
pub.subscribe(self.sub_channel) #订阅指定频道
pub.parse_response() #解析收到的消息,在正式接受消息前,要先接收一条来自发布方的确认消息。
return pub
* 发布方:可以直接在命令行里用PUBLISH命令发布消息,也可用python模拟:
#Downtiser
import redis
from redis_mod.redis_class import redis_handler
redis_obj = redis_handler()
while True:
message = input('请输入想要发布的消息>>>')
redis_obj.pub(message)
* 接受方: 可以在命令行用SUBSCRIBE命令接受多个频道的消息,也可用python模拟:
#Downtiser
import redis
from redis_mod.redis_class import redis_handler
redis_obj = redis_handler()
subscriber = redis_obj.sub()
print('----开始接受消息----')
while True:
message_list = subscriber.parse_response() #开始接受消息,如果没收到就阻塞,收到消息会将消息和频道等组成一个列表
print(message_list,message_list[-1].decode())