zoukankan      html  css  js  c++  java
  • redis模块

    redis模块用于调用操作redis,而redis是一个基于内存的高性能key-value的存储系统,支持存储的类型有string、list、set、zset和hash。在处理大规模数据读写或高效的缓存的场景下运用比较多。


    redis模块中实现了两个类来操作数据库,分别是Redis和StricRedis

    redis模块中允许两种连接方式直接连接和连接池连接

    连接池的原理是,通过预先创建多个连接, 当进行redis操作时,直接获取已经创建的连接进行操作,而且操作完成后,不会释放,用于后续的其他redis操作,这样就达到了避免频繁的redis连接创建和释放的目的,从而提高性能。redis模块采用ConnectionPool来管理对redis server的所有连接。

    # 以StricRedis举例
    from redis import StrictRedis, ConnectionPool
    
    # 直接连接
    # 使用默认方式连接到数据库
    redis = StrictRedis(host='localhost', port=6379, db=0)
    
    # 使用url方式连接到数据库
    redis = StrictRedis.from_url('redis://@localhost:6379/1')
    
    
    # 连接池连接
    # 使用默认方式连接到数据库
    pool = ConnectionPool(host='localhost', port=6379, db=0)
    redis = StrictRedis(connection_pool=pool)
    
    # 使用url方式连接到数据库
    pool = ConnectionPool.from_url('redis://@localhost:6379/1')
    redis = StrictRedis(connection_pool=pool)

    有三种构造url的方式:

    redis://[:password]@host:port/db    # TCP连接
    rediss://[:password]@host:port/db   # Redis TCP+SSL 连接
    unix://[:password]@/path/to/socket.sock?db=db    # Redis Unix Socket 连接

    redis中有五种数据类型:字符串(String)、哈希(Hash)、列表(List)、集合(Set)、有序集合(sorted set)

    哈希是一个string类型的field和value的映射表,hash特别适合用于存储对象。

    列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部或者尾部。

    集合是String类型的无序集合。集合成员是唯一的,意味着集合中不能出现重复的数据。

    有序集合和集合大致相同,不同的是每个元素都会关联一个double类型的分数。通过分数来为集合中的成员进行从小到大的排序。有序集合的成员是唯一的,但分数(score)却可以重复。


    默认情况下,响应以 Python3 的字节Python 2 的 str 形式返回,用户负责解码操作。

    String类型操作:

    1. set(name, value):设置成功返回True

    # 在Redis中设置值,默认不存在则创建,存在则修改
    set(name, value, ex=None, px=None, nx=False, xx=False)
    # 参数:
    # ex-过期时间(秒)
    # px-过期时间(毫秒)
    # nx-如果设置为True,则只有key不存在时,当前set操作才执行,同#setnx(key, value)
    # xx-如果设置为True,则只有key存在时,当前set操作才执行

    2. mset(*args, **kwargs)

    # 批量设置值
    redis.mset({"key1":'value1', "key2":'value2'})

    3. get(name):返回获取到的值

    # 获取某个key的值
    redis.get('key1')

    4. mget(keys, *args):返回获取到的值列表

    # 批量获取
    redis.mget("key1","key1")

    5. strlen(name)

    # 返回key对应值的字节长度(一个汉字3个字节)
    redis.strlen("key")

    6. append(name, value)

    # 在name对应的值后面追加内容
    redis.set("key","value")
    print(redis.get("key"))    # 输出:'value'
    redis.append("key","one")
    print(redis.get("key"))    # 输出:'valueone'

    7. substr(name, start, end=-1)

    # key为name的string的value的子串,start为起始索引,end为结束索引
    redis.set('key','value')
    redis.substr('key', 1, 4)  # 输出‘alue’

    8. getrange(key, start, end)

    # 获取key的value值从start到end的子字符串
    redis.set("key", "value")
    redis.getrange('key', 1, 4)  # 输出 'alue'

    9. getset(name, value):给数据库中key为name的string赋予值value并返回上次的value

    10. setnx(name, value):如果key不存在才设置value,操作成功返回True

    11. setex(name, time, value):设置可以对应的值为string类型的value,并指定此键值对应的有效期(秒),操作成功返回True

    12. setrange(name, offset, value):设置指定key的value值的子字符串,返回修改后的字符串长度

    13. msetnx(mapping):key均不存在时才批量赋值,操作成功返回True

    14. incr(name, amount=1):key为name的value增值操作,默认1,key不存在则被创建并设为amount,返回修改后的值

    15. decr(name, amount=1):key为name的value减值操作,默认1,key不存在则被创建并设置为-amount,返回修改后的值

    Hash类型操作:

    1. hset(name, key, value):返回键值对添加个数

    # name对应的hash中设置一个键值对(不存在,则创建,否则,修改)
    redis.hset("name","key","value")

    2. hget(name, key)

    redis.hset("name","key","value")
    # 在name对应的hash中根据key获取value
    print(redis.hget("name","key"))  # 输出:'value'

    3. hgetall(name)

    # 获取name所有键值对
    redis.hgetall("name")

    4. hmset(name, mapping)

    # 在name对应的hash中批量设置键值对,mapping:字典
    dic={"key1":"aa","key2":"bb"}
    redis.hmset("name",dic)
    print(redis.hget("name","key2"))  # 输出:bb

    5. hmget(name, keys, *args)

    # 在name对应的hash中批量获取键所对应的值
    dic={"key1":"aa","key2":"bb"}
    redis.hmset("name",dic)
    print(redis.hmget("name","key1","key2"))  # 输出:['aa', 'bb']

    6. hlen(name)

    # 获取hash键值对的个数
    print(redis.hlen("name"))  # 输出:2

    7. hkeys(name)

    # 获取hash中所有key
    redis.hkeys("name")

    8. hvals(name)

    # 获取hash中所有value
    redis.hvals("name")

    9. hexists(name, key)

    # 检查name对应的hash是否存在当前传入的key
    print(redis.hexists("name","key1"))  # 输出:Ture

    10. hdel(name, *keys)

    # 删除指定name对应的key所在的键值对,删除成功返回1,失败返回0
    print(redis.hdel("name","key1"))  # 输出:1

    11. hincrby(name, key, amount=1)

    # 与hash中key对应的值相加,不存在则创建key=amount(amount为整数)
    print(redis.hincrby("name","key",amount=10))  # 返回:10

    12. hsetnx(name, key, value):向key为name的hash中添加映射,如果映射键名不存在执行,返回添加键值对的个数

    list类型操作:

    1. lpush(name, *values)

    # 元素从list的左边添加,可以添加多个
    redis.lpush('name','元素1','元素2')

    2. rpush(name, *values)

    # 元素从list右边添加,可以添加多个
    redis.rpush('name','元素1','元素2')

    3. lpushx(name, *values)

    # 当name存在时,元素才能从list的左边加入
    redis.lpushx('name','元素1')

    4. rpushx(name, *values)

    # 当name存在时,元素才能从list的右边加入
    redis.rpushx('name','元素1')

     5. llen(name)

    # name列表长度
    redis.llen('name')

    6. linsert(name, where, refvalue, value)

    # 在name对应的列表的某一个值前或后插入一个新值
    redis.linsert("name","BEFORE","元素2","元素1.5")#在列表内找到第一个"元素2",在它前面插入"元素1.5" # 参数: # name: redis的name # where: BEFORE(前)或AFTER(后) # refvalue: 列表内的值 # value: 要插入的数据

    7. lset(name, index, value)

    # 对list中的某一个索引位置重新赋值, 越界则报错
    redis.lset("name",0,"abc")

    8. lrem(name, value, num=0)

    # 删除name对应的list中的指定值
    redis.lrem("name","元素1",num=0)
    
    # 参数:
    # name: redis的name
    # value: 要删除的值
    # num: num=0 删除列表中所有的指定值
    #      num=2 从前到后,删除2个
    #      num=-2 从后向前,删除2个

    9. lpop(name):rpop(name)移除右侧第一个元素

    # 移除列表的左侧第一个元素,返回值则是第一个元素
    print(redis.lpop("name"))

    10. lindex(name, index)

    # 根据索引获取列表内元素
    print(redis.lindex("name",1))

    11. lrange(name, start, end)

    # 分片获取元素
    print(redis.lrange("name",0,-1))

    12. ltrim(name, start, end)

    # 移除列表内没有在该索引之内的值
    redis.ltrim("name",0,2)

    13. blpop(name, timeout=0):返回并删除名称为在keys中的list中的首元素,如果list为空,则会一直阻塞等待

    14. brpop(name, timeout=0):返回并删除key为name的list中的尾元素,如果list为空,则会一直阻塞等待

    15. rpoplpush(src, dst):返回并删除名称为src的list的尾元素,并将该元素添加到名称为dst的list的头部

    set类型操作:

    1. sadd(name, *values)

    # 给name对应的集合中添加元素
    redis.sadd("name","aa")
    redis.sadd("name","aa","bb")

    2. scard(name)

    # 获取name对应的集合中的元素个数
    redis.scard("name")

    3. smembers(name)

    # 获取name对应的集合的所有成员
    redis.smembers('name')

    4. sdiff(keys, *args):返回所有给定key的set的差集

    # 在第一个name对应的集合中且不在其他name对应的集合的元素集合
    redis.sadd("name","aa","bb")
    redis.sadd("name1","bb","cc")
    redis.sadd("name2","bb","cc","dd")
    print(red.sdiff("name","name1","name2"))#输出:{aa}

    5. sismember(name, value) :检查value是否是name对应的集合内的元素

    6. smove(src, dst, value):将某个元素从一个集合中移动到另外一个集合

    7. spop(name):随机返回并删除key为name的set中一个元素

    8. srem(name, *values):从key为name的set中删除元素

    9. sinter(keys, *args):返回所有给定key的set的交集

    10. sinterstore(dest, keys, *args):求交集并将交集保存到dest的集合

    11. sunion(keys, *args):返回所有给定key的set的并集

    12. sunionstore(dest, keys, *args):求并集并将并集保存到dest的集合

    13. sdiffstore(dest, keys, *args):求差集并将差集保存到dest的集合

    14. srandmember(name):随机返回key为name的set的一个元素,但不删除元素

    Sorted Set类型操作:

    1. zadd(name, args, *kwargs):向key为name的zset中添加元素member,score用于排序。如果该元素存在,则更新其顺序

    redis.zadd('grade', 100, 'Bob', 98, 'Mike')

    2. zrem(name, *values):删除key为name的zset中的元素

    redis.zrem('grade', 'Mike')

    3. zincrby(name, value, amount=1):如果在key为name的zset中已存在元素value,则该元素的score增加amount,否则向该集合中添加该元素,score的值为amount

    4. zrank(name, value):返回key为name的zset中元素的排名(按score从小到大排序)即下标

    5. zrevrank(name, value):返回key为name的zset中元素的倒数排名(按score从大到小排序)即下标

    6. zrevrange(name, start, end, withscores=False):返回key为name的zset(按score从大到小排序)中的index从start到end的所有元素,默认不带分值

    7. zrangebyscore(name, min, max, withscores=False):返回key为name的zset中score在给定区间的元素

    8. zcount(name, min, max):返回key为name的zset中score在给定区间的数量

    9. zcard(name):返回key为name的zset的元素个数

    10. zremrangebyrank(name, min, max):删除key为name的zset中排名在给定区间的元素

    11. zremrangebyscore(name, min, max):删除key为name的zset中score在给定区间的元素

    其他常用操作:

    flushdb(asynchronous=False):清空当前db中的数据,默认是同步。若开启异步asynchronous=True,会新起一个线程进行清空操作,不阻塞主线程

    flushall(asynchronous=False):清空所有db中的数据,默认是同步。异步同flushdb

    delete(*names):根据name删除redis中的任意数据类型

    exists(name):判断一个key是否存在

    keys(pattern='*'):根据* ?等通配符匹配获取redis的name,*任意多个字符

    expire(name, time):为某个name的设置过期时间,单位秒

    rename(src, dst):重命名

    move(name, db)):将redis的某个name移动到指定的db下

    randomkey():随机获取一个redis的name(不删除)

    type(name):获取name对应值的类型

    dbsize():获取当前数据库中key的数目

    ttl(name):获取key的过期时间,单位秒,-1为永久不过期


    RedisDump

    redis-load:将数据导入到数据库中

    redis-load -h   # 获取帮助信息
    
    < redis_data.json redis-load -u redis://@localhost:6379  # 将json数据导入数据库中

    redis-dump:将数据库信息导出

    redis-dump -h  # 获取帮助信息
    
    redis-dump -u redis://@localhost:6379 -d 1 > ./redis.data.jl  # 导出到json文件
    redis-dump -u redis://@localhost:6379 -f adsl:* > ./redis.data.jl  # 导出adsl开头的数据

    StricRedis类和Redis类的区别:

    StricRedis类尽量坚持官方语法,除了以下命令:

    • select 没有实现,考虑到了线程安全

    • del Python 关键字,用 delete 代替

    • config get|se 作为 config_get / config_set 实现

    • multi / exec 作为 Pipeline 类的一部分实现的

    Redis 类是 StricRedis 的子类,提供向后的兼容性。推荐使用 StricRedis。Redis 覆盖了几个命令:

    • lrem num 和 value 参数顺序颠倒,num 提供默认值 0

    • zadd Redis类期望* args的形式为:name1,score1,name2,score2,...,而 StricRedis 是 score1,name1,score2,name2,...,这与 Redis 一样

    • setex time 和 value 顺序颠倒。在 Redis 类中是:setex(key, value, time),在 StricRedis 类中是:setex(key, time, value)


    管道

    管道一般用来执行事务操作

    r = redis.Redis(...)
    r.set('bing', 'baz')
    pipe = r.pipeline()
    pipe.set('foo', 'bar')
    pipe.get('bing')
    pipe.execute()  # 输出 [True, 'baz']

    管道也可进行链式操作

    pipe.set(' foo '' bar ').sadd(' faz '' baz ').incr(' auto_number ').execute()
    # 输出 [True,True,6]

    可禁用原子性:

    pipe = r.pipeline(transaction = False)

    WATCH 监控命令:

    with r.pipeline() as pipe:
         while 1:
            try:
                # 设置一个 watch
                 pipe.watch('OUR-SEQUENCE-KEY')
                 current_value = pipe.get('OUR-SEQUENCE-KEY')
                 next_value = int(current_value) + 1
                 # 开始事务
                 pipe.multi()
                 pipe.set('OUR-SEQUENCE-KEY', next_value)
                 # 执行
                 pipe.execute()
                 # 如果抛出 WatchError ,表示原子性失败
                 break
            except WatchError:
                 # 另一个客户端修改了,我们必须重试
                 continue

    由于Pipeline在watch期间绑定到单个连接,必须调用reset()来确保返回连接池,使用with上下文的话,它会自动调用。当然也可以手动调用:

    pipe = r.pipeline()
    while 1:
         try:
             pipe.watch('OUR-SEQUENCE-KEY')
             ...
             pipe.execute()
             break
         except WatchError:
             continue
         finally:
             pipe.reset()

    也可以使用 transaction() 方法来简化操作

    def client_side_incr(pipe):
         current_value = pipe.get('OUR-SEQUENCE-KEY')
         next_value = int(current_value) + 1
         pipe.multi()
         pipe.set('OUR-SEQUENCE-KEY', next_value)
    
    r.transaction(client_side_incr, 'OUR-SEQUENCE-KEY')  # 输出 [True]

    线程安全问题:

    可以在线程之间安全地共享 Redis 客户端实例。有一点需要注意:Redis SELECT命令。SELECT命令允许您切换连接当前使用的数据库。该数据库保持选定状态直到选择另一个数据库或连接关闭。这会产生一个问题,即连接可以返回到连接到不同数据库的池。因此不会实现 select 命令。 在线程之间传递PubSub或Pipeline对象是不安全的。
  • 相关阅读:
    静态代理和动态代理
    Tomcat的作用思考及NIO的应用(要区分Java NIO和操作系统的NIO模型)
    破坏双亲委托机制的一些情况---Tomcat和JDBC,破坏后的安全问题
    springboot cache---本地缓存的使用
    springboot--异步执行的方法及定时执行的方法
    springboot--事务的使用
    数据结构--堆排序
    数据结构--树的非递归遍历
    最长公共子串的长度和构造
    2015 小结及其2016计划
  • 原文地址:https://www.cnblogs.com/eat-w/p/12060910.html
Copyright © 2011-2022 走看看