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的几个参数:
      1. ex:过期时间,s
      2. px:过期时间,ms
      3. nx: 默认为False,若为Ture,只有指定的key不存在时set的value才会生效
      4. 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,所以再getname的值就变为了E。另外,设置的位不局限与该字符串,可以是任意位数,例如set name 10000 1也是可操作的
    • bitcount: 统计一个value的二进制形式中位值为1的位的个数,例如BITCOUNT nn的值为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
  • 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并返回键值对
  • 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 阻塞时间将第一个列表最右边值移除并添加到另一个列表的最左边
  • 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的成员
  • 有序集合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:跟列表的类似
  • 其他常用操作:
    • 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())