• redis的使用


    1. redis介绍

    redis是一个key-value存储系统, 速度快, 支持丰富数据类型, 支持事务, 支持持久化, 丰富的特性...
    
    • 1
    速度快: 因为数据存在内存中, 类似于HashMap, HashMap的优势就是查找和操作的时间复杂度都是O(1)
           使用I/O多路复用, 是单进程单线程的架构, 避免了线程和进程之间切换的资源消耗.
    支持丰富数据类型: 支持string, list, set, sorted set(有序集合), hash(字典)
    支持事务:操作都是原子性, 所谓的原子性就是对数据的更改要么全部执行, 要么全部不执行.
    支持持久化: 将数据存到硬盘中.
    丰富的特性:可用于缓存, 消息, 按key设置过期时间, 过期后将会自动删除.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    PS: Memcached:另一个key-value存储系统, 操作更简洁.
        只支持字符串类型数据, 不支持持久化, 数据断电丢失.
    
    • 1
    • 2
    redis适合的场景:
        1 排行榜 (使用 sorted set数据类型)
        2 网站访问量, 文章访问量 
        3 缓存数据库(str 缓存接口 hash)
        4 发布订阅
        5 去重(set类型)
        6 分布式blpop (类别类型)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2. redis安装

    * 1. 官方不支持Windows版本的Redis, 因此官网上不提供下载.
    	 但微软开发和维护着支持win-64的Redis版本, 因此可以去下载.
         地址: https://github.com/MicrosoftArchive/redis/releases
    
    • 1
    • 2
    • 3

    image-20220524124736935

    MSI文件是Windows Installer的数据包, 它实际上是一个数据库.
    包含安装一种产品所需要的信息和在很多安装情形下安装(和卸载)程序所需的指令和数据.
    
    • 1
    • 2
    * 2. 点击安装包安装(包含服务端和客户端)
    
    • 1

    GIF 2022-5-24 12-56-19

    勾选 Add the Redis installation filder to the PATH environment variable. 添加到环境变量
    端口 6379, 不限制使用的内存大小.
    
    • 1
    • 2

    image-20220524130440280

    服务端会自动添加到windows的服务中, 自动启动.
    这个服务使用 redis-server 配置文件.conf 启动服务端.
    
    • 1
    • 2
    * 3. 客户端连接服务端
    	 redis-cli -h 地址 -p 端口 连接服务端
    	 redis-cli 命令默认使用127.0.0.1  6379
    
    • 1
    • 2
    • 3
    * 4. 存值&取值&退出
         存值: set key 
         取值: get key
         退出: exit
    
    • 1
    • 2
    • 3
    • 4

    image-20220524131016467

    3. redis桌面管理器

    该工具为您提供了一个易于使用的GUI, 可以访问您的Redis数据库并执行一些基本操作:
    将键视为树, CRUD键, 通过shell执行命令.
    官网: https://redisdesktop.com/download
    
    • 1
    • 2
    • 3
    * 1. 安装步骤
    
    • 1

    GIF 2022-5-24 13-24-44

    * 2. 连接服务端
    
    • 1

    2022-05-24_00889

    * 3. 基操, 嘿嘿
    
    • 1

    2022-05-24_00891

    4. Python连接redis

    * 1. 安装redis模块
    	 pip install redis
    
    • 1
    • 2
    * 2. 简单使用
    
    • 1
    from redis import Redis
    
    # host = "localhost", port = 6379,
    conn = Redis()  # 生成连接对象, 连接一次
    
    # (str, bytes) 值都会被转换为bytes类型
    conn.set('age', 18)  # 存值
    res = conn.get('age')  # 取值
    
    print(res)  # b'18'
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    decode_response=True 参数对取出的值进行解码.
    
    • 1
    from redis import Redis
    
    # decode_response=True 对取出的值进行解码.
    conn = Redis(decode_responses=True)  # 生成连接对象, 连接一次
    
    # (str, bytes) 值都会被转换为bytes类型
    conn.set('age', 18)  # 存值
    res = conn.get('age')  # 取值
    
    print(res)  # 18
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    ps: QPS: 指每秒查询率。
    redis的QPS 10, 实际测试在6万多.
    
    • 1
    • 2

    5. 连接池

    正确访问操作一次连接一次, 如果项目中建立很多连接, 会影响redis的性能.
    连接池: (一次连接就会使用一个连接对象)
    在项目运行时先创建固定个数的连接对象, 放进连接池(列表).
    需要操作redis时, 从连接池中随机拿一个连接对象, 操作完之后再放进连接池.
    
    • 1
    • 2
    • 3
    • 4
    连接池是一个单例模式.
    单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在.
    当你希望在整个系统中, 某个类只能出现一个实例时, 单例对象就能派上用场.
    
    • 1
    • 2
    • 3
    模块实现方式:
    python 的模块就是天然的单例模式, 因为模块在第一次导入时, 会生成 .pyc 文件.
    当第二次导入时, 就会直接加载 .pyc 文件, 而不会再次执行模块代码.
    因此, 我们只需把相关的函数和数据定义在一个模块中, 就可以获得一个单例对象了.
    
    • 1
    • 2
    • 3
    • 4
    * 1. connection_pool.py 中创建连接池
    
    • 1
    # 导入redis
    import redis
    
    
    # 创建连接池 max_connections, 设置连接池的数量
    POOL = redis.ConnectionPool(max_connections=100)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    * 2. test_redis.py 中使用连接池的对象
    
    • 1
    # 导入连接池
    from connection_pool import POOL
    
    import redis
    # 从连接池中获取到一个连接对象
    conn = redis.Redis(connection_pool=POOL)
    # 通过连接对象操作redis
    print(conn.get('name'))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    6. 字符串类型使用

    set 没有值则创建值, 值存在则修改值.
    set(key, value, ex, px, nx, xx)
    key: 
    value: 
    ex: 过期时间()
    px: 过期时间(毫秒)
    nx: 设置为True, 当key不存在的时候, set操作才会生效. (新建增的操作)
    xx: 设置为True, 当key存在的时候, set操作才会生效. (修改值的操作)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    6.1 存值取值

    set(key, value) 设置值
    get(key) 取值
    getset(key, value) 先取值在刷新值
    
    • 1
    • 2
    • 3
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    # 存值
    conn.set('k1', 1)
    
    # 取值在刷新值
    res = conn.getset('k1', 2)
    print(res)  # b'1'
    
    # 取值
    print(conn.get('k1'))  # b'2'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    6.1 过期时间

    set('key', 'value', ex) ==> setex('key', 'value', '过期时间, 秒') 
    set('key', 'value', px) ==> psetex('key', '过期时间, 毫秒', 'value') 
    
    • 1
    • 2
    from connection_pool import POOL
    import time
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    # 设置3秒过去
    conn.set('k1', 'v1', 3)
    res = conn.get('k1')
    print(res)  # b'v1'
    
    # 延时4秒
    time.sleep(4)
    res = conn.get('k1')
    print(res)  # None
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    6.2 写入限制

    set('key', 'value', nx) ==> setnx('key', 'value') 
    
    • 1
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    # set没有写入
    conn.set('k1', 'v1')
    res = conn.get('k1')
    print(res)  # b'v1'
    
    # 写入限制, 键已经存在, set操作失效
    conn.set('k1', 'v2', nx=True)
    res = conn.get('k1')
    print(res)  # b'v1'
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    6.3 修改限制

    set('key', 'value', xx) ==> setxx('key', 'value') 
    
    • 1
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    res = conn.get('k4')  # None
    print(res)  # None
    
    # 限制修改, 当key存在才能修改
    conn.set('k4', 'v4', xx=True)
    res = conn.get('k4') 
    print(res)  # None
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    6.4 批量操作

    批量设置
    mset({'k1': 'v1', 'k2': 'v2'})
    
    批量取值
    mget('k1', 'k2')
    
    批量设置并取值
    mget({'k1': 'v1', 'k2': 'v2'})  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    # 批量插值
    conn.mset({'k1': 'v1', 'k2': 'v2'})
    # 批量获取
    print(conn.mget('k1', 'k2'))  # [b'v1', b'v2']
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    # 批量设置并取值
    print(conn.mget({'k1': 'v1', 'k2': 'v2'}))  # [b'v1', b'v2']
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    6.5 区间取值

    getrange(key, start, end) 区间取值, 前比后闭区间, 顾前顾后.
    
    • 1
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    conn.set('k1', 123)
    
    print(conn.getrange('k1', 0, 0))  # b'1'
    print(conn.getrange('k1', 0, 1))  # b'12'
    print(conn.getrange('k1', 0, 2))  # b'123'
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    6.6 替换

    一个汉字占三位.
    
    • 1
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    conn.set('k1', 123)
    
    conn.setrange('k1', 1, 789)  # 设置一个游标, 从这个游标开始切换后面所有的值
    
    print(conn.get('k1'))
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    6.7 bit操作

    value的二进制表示值操作
    
    • 1
    修改位: setbit(key, , 1/0) (值只能是0/1)
    
    • 1
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    # goo 的二进制为 01100110 01101111 01101111
    conn.set('str1', 'goo')
    # 修改为 01101111 01101111 01101111
    conn.setbit('str1', 4, 1)  # 正数第5位改为1, 从0开始
    conn.setbit('str1', 7, 1)  # 正数第8位改为1, 从0开始
    
    print(conn.get('str1'))  # b'ooo'
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    获取位: getbit(key, )
    
    • 1
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    # goo 的二进制为 01100110 01101111 01101111
    conn.set('str1', 'goo')
    print(conn.getbit('str1', 0))  # 0
    print(conn.getbit('str1', 1))  # 1
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    统计位: bitcount(key, strat, end) 获取值对应值的二进制数1的个数
    
    • 1
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    # goo 的二进制为 01100110 01101111 01101111
    print(conn.bitcount('str1'))  # 17
    
    print(conn.bitcount('str1', 0, 0))  # 5   0, 0 第一个字符对应的二进制
    print(conn.bitcount('str1', 0, 1))  # 11  0, 1 第一个第二个字符对应的二进制
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    bitop (operation, dest, *keys)
    参数: 
    operation, AND(), OR(), NOT(, key只能有1), XOR(异或)
    dest 新的redis的key
    *key 需要查询的key, 可以是多个key.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    # o 的二进制为   01101111
    
    conn.mset({'k1': 'o', 'k2': 'o'})
    print(conn.mget('k1', 'k2'))  # [b'o', b'o']
    
    conn.bitop('AND', 'k3', 'k1', 'k2')  # AND 一一得一 零零得零
    
    print(conn.get('k3'))  # b'o'
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    strlen(key)  返回value的字节格式, 一个汉字三个字节.
    
    • 1
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    # o 的二进制为   01101111
    
    conn.set('k1', '你好')
    print(conn.strlen('k1'))  # 6
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    6.8 自增/自减

    incr(self, key, amount=1) ==> incrby() 调用一次计数加1, amount可以设置, 
    decr(self, key) 调用一次计数减1
    incrbyfloat(self, name, amount=1.0) 当可以没有值时, key = amount, 否则自增.
    
    • 1
    • 2
    • 3
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    # o 的二进制为   01101111
    
    conn.set('k1', 0)
    conn.incr('k1')  # 计算+1
    conn.incr('k1')  # 计算+1
    conn.incr('k1')  # 计算+1
    print(conn.get('k1'))  # b'3'
    
    conn.decr('k1')
    print(conn.get('k1'))  # b'2'
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    # o 的二进制为   01101111
    
    conn.set('k1', 0)
    
    conn.incr('k1', 2)
    
    print(conn.get('k1'))  # b'2'
    
    conn.incr('k1', -2)
    
    print(conn.get('k1'))  # b'0'
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    
    conn.incrbyfloat('k1')
    print(conn.get('k1'))  # b'1'
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    6.9 追加

    append(key, value) 在key对应的值后面追加内容
    
    • 1
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    conn.set('k1', 'hello')
    conn.append('k1', ' word!')
    print(conn.get('k1'))  # b'hello word!'
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    7. hash类型操作

    hset(name, key, value) 存值
    hsetnx(name, key, value)  name对应的hash的key不存在时则创建.
    hget(name, key) 取值
    name: redis的name
    key hash的key
    value hash的value
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    conn.hset('n1', 'k1', 'v1')
    print(conn.hget('n1', 'k1'))  # b'v1'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    7.1 批量设置

    hmset(name,{key1: value1, key2: value2}) 存多个值
    hgset(name, k1, k2) / hgset(name, [k1, k2]) 去多个值
    
    • 1
    • 2
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    # DeprecationWarning: Redis.hmset() is deprecated. Use Redis.hset() instead. 弃用警告
    conn.hmset('n1', {'k1': 'v1', 'k2': 'v2'})
    print(conn.hmget('n1', 'k1', 'k2'))  # [b'v1', b'v2']
    print(conn.hmget('n1', ['k1', 'k2']))  # [b'v1', b'v2']
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    7.2 查询所有

    hgetall(name) 获取name对应的hash所有键值对.
    
    • 1
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    # DeprecationWarning: Redis.hmset() is deprecated. Use Redis.hset() instead. 弃用警告
    conn.hmset('n1', {'k1': 'v1', 'k2': 'v2'})
    print(conn.hgetall('n1'))  # {b'k1': b'v1', b'k2': b'v2'}
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    7.3 获取个数

    hlen(name)  获取name对应hash的所有键值对个数.
    
    • 1
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    # DeprecationWarning: Redis.hmset() is deprecated. Use Redis.hset() instead. 弃用警告
    conn.hmset('n1', {'k1': 'v1', 'k2': 'v2'})
    print(conn.hlen('n1'))  # 2
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    7.4 获取所有键/值

    hkeys(name)  获取name对应的hash所有的键
    hvals(name)  获取name对应的hash所有的值
    
    • 1
    • 2
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    # DeprecationWarning: Redis.hmset() is deprecated. Use Redis.hset() instead. 弃用警告
    conn.hmset('n1', {'k1': 'v1', 'k2': 'v2'})
    print(conn.hkeys('n1'))  # [b'k1', b'k2']
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    # DeprecationWarning: Redis.hmset() is deprecated. Use Redis.hset() instead. 弃用警告
    conn.hmset('n1', {'k1': 'v1', 'k2': 'v2'})
    print(conn.hvals('n1'))  # [b'v1', b'v2']
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    7.5 判断键是否存在

    hexists(name, key)  判断hash中是否存在某个键
    
    • 1
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    # DeprecationWarning: Redis.hmset() is deprecated. Use Redis.hset() instead. 弃用警告
    conn.hmset('n1', {'k1': 'v1', 'k2': 'v2'})
    print(conn.hexists('n1', 'k1'))  # True
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    7.6 删除键

    hdel(name, *keys)  将指定的key从hash中删除.
    
    • 1
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    # DeprecationWarning: Redis.hmset() is deprecated. Use Redis.hset() instead. 弃用警告
    conn.hmset('n1', {'k1': 'v1', 'k2': 'v2'})
    print(conn.hdel('n1', 'k1'))  # 1
    print(conn.hgetall('n1'))  # {b'k2': b'v2'}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    7.7 自增

    hincrby(namen, key, amount=1)  自增
    hincrbyfloat(namen, key, amount=1.0)
    
    • 1
    • 2
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    # DeprecationWarning: Redis.hmset() is deprecated. Use Redis.hset() instead. 弃用警告
    conn.hset('n1', 'k1', 0)
    print(conn.hincrby('n1', 'k1'))  # 1
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    7.8 迭代取值

    hscan(name, cursor=0, match=None, count=None)
    增量式迭代获取, 可以实现切片获取数据, 并非一次性将全部取出, 全局取出数据太大会撑爆内存.
    对数据量大的数据非常有用.
    name: redis的name
    cursor: 游标(基于游标批量获取数据)
    match: 匹配指定key, 默认为None, 表示所有的Key
    count: 每次分片最少获取格式, 默认None表示采用Redis的默认分片个数.
    
    hscan_iter(name, match=None, count=None)
    利用yield封装hscan创建生成器, 实现分批去redis中获取数据.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    # DeprecationWarning: Redis.hmset() is deprecated. Use Redis.hset() instead. 弃用警告
    conn.hmset('n1', {'k1': 'v1', 'k2': 'v2', 'k3': 'v3', 'k4': 'v4', })
    print(conn.hscan('n1'))  # (0, {b'k2': b'v2', b'k1': b'v1', b'k3': b'v3', b'k4': b'v4'})
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    # DeprecationWarning: Redis.hmset() is deprecated. Use Redis.hset() instead. 弃用警告
    conn.hmset('n1', {'k1': 'v1', 'k2': 'v2', 'k3': 'v3', 'k4': 'v4', })
    
    # 取数据量大的值, 不建议使用hgetall, 建议使用hscan_iter
    # 一次性先取一部分, 做成生成器, 反复如此.
    res = conn.hscan_iter('n1')
    print(res)  # <generator object ScanCommands.hscan_iter at 0x000001E155FD1040>
    
    for i in res:
        print(i)
    """
    (b'k2', b'v2')
    (b'k1', b'v1')
    (b'k3', b'v3')
    (b'k4', b'v4')
    """
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    7.9 其他

    smove(rec, dstm value) 将某个成员从一个集合移动动到另一个集合
    spop(name)  从集合的右侧(尾部)弹出一个成员, 并将其放回.
    srandmenber(name, numbers) 从nane对应的集合移除numbers指定个数的元素
    ...
    
    • 1
    • 2
    • 3
    • 4

    8. 列表操作

    8.1 存取值

    lpush(name, *values)  从左侧插值 后写的数据 ---> 先写的数据
    rpush(name, *values)  从右侧插值 先写的数据 <--- 后写的数据
    
    name存在才能写入
    rpushx(name, values)  
    lpushx(name, values)
    
    lrange 获取list指定索引区间的数据
    lrange(name, start, end)
    name: 列表名称
    start: 开始的索引值
    end: 结束的索引值
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    res = conn.lpush('list1', 1, 2, 3, 4, 5)
    print(res)  # 5 插入的数据量
    
    print(conn.lrange('list1', 0, -1))  # [b'5', b'4', b'3', b'2', b'1']
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    image-20220525153108031

    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    res = conn.rpush('list2', 1, 2, 3, 4, 5)
    print(res)  # 5 list2的数据量
    
    print(conn.lrange('list2', 0, -1))  # [b'1', b'2', b'3', b'4', b'5']
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    image-20220525153223727

    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    res1 = conn.rpushx('list3', 1, )
    res2 = conn.lpushx('list4', 1, )
    print(res1)  # 0 list3的数据量
    print(res2)  # 0 list3的数据量
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    8.2 统计长度

    llen(name) 统计name对应的列表的长度.
    
    • 1
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    conn.lpush('list5', 1, 2, 3)
    res = conn.llen('list5')
    
    print(res)  # 3 list5长度
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    8.3 插入值

    linsert(name, where, refvalue, value)
    name: redis的name
    where: BEFORE  AFTER (大小写都可以, before .. after在..)
    refvalue: 游标值, : 它在前后插入数据(如果有多个游标值, 以找打的第一个为准)
    value: 要插入的数据
    
    • 1
    • 2
    • 3
    • 4
    • 5
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    conn.lpush('list6', 1, 2, 3)
    # 游标是值, 在3的前面插入a, 在3d的后面插入b
    conn.linsert('list6', 'BEFORE', 3, 'a')
    conn.linsert('list6', 'AFTER', 3, 'b')
    
    print(conn.lrange('list6', 0, -1))  # [b'a', b'3', b'b', b'2', b'1']
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    image-20220525162530643

    8.4 依据索引设置值

    lset(name, index, value) index从0开始
    
    • 1
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    conn.lpush('list8', 1, 2, 3)
    res1 = conn.lset('list8', 2, 'a')
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    image-20220525163652039

    8.5 弹出值

    lpop(name)  左弹
    rpop(name)  右弹
    
    rpoplpush(src, des) 从一个列表取出最右边的的元素, 同时将其添加到另一个列表的最左边.
    
    src 要取数据的列表name
    dst 要添加数据的列表name
    
    
    blpop(name, timeout) 
    brpop(name, timeout) 
    timeout 超时时间, 超时后还没值, 返回None. timeout=0表示永久.
    
    brpoplpush(src, des, timeout)  从一个列表取出最右边的的元素, 同时将其添加到另一个列表的最左边.
    值没有了就hang住等待.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    conn.lpush('list7', 1, 2, 3)
    res1 = conn.rpop('list7')  # 右弹
    print(res1)  # b'1'
    conn.rpop('list7')
    conn.rpop('list7')
    print(conn.rpop('list7'))  # None
    
    # 左弹
    res2 = conn.lpop('list7')  # b'3'
    print(res2)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    # -                  4  3  2  1  0
    conn.lpush('list13', 1, 2, 3, 4, 5)
    print(conn.lrange('list13', 0, -1))  # [b'5', b'4', b'3', b'2', b'1']
    
    conn.rpoplpush('list13', 'list14')
    print(conn.lrange('list14', 0, -1))  # [b'1']
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    # test_redis.py 先运行
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    conn.lpush('list14', 1, 2, 3)
    
    print(conn.blpop('list14'))
    print(conn.blpop('list14'))
    print(conn.blpop('list14'))
    print(conn.blpop('list14'))  # hang在此, 可以作为消息队列, 另一个成功往列表中插值
    
    # test_redis2.py 后运行
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    conn.lpush('list14', 4)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    image-20220525173703003

    8.6 删除值

    lrem(name, count, value)
    name: 对应的list中删除指定的值
    
    count=0: 删除列表中所有的指定值(列表中的值可以重复)
           count=2  从前到后, 删除两个value指定的值
           count=-2 从后向前, 删除两个value指定的值	
    value: 要删除的值
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    conn.lpush('list10', 1, 2, 3, 4, 5)
    print(conn.lrange('list10', 0, -1))  # [b'5', b'4', b'3', b'2', b'1']
    
    conn.lrem('list10', count=0, value=1)
    print(conn.lrange('list10', 0, -1))  # [b'5', b'4', b'3', b'2']
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    8.7 索引取值

    lindex(name, index)  依据索引取值
    
    • 1
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    conn.lpush('list11', 1, 2, 3, 4, 5)
    print(conn.lindex('list11', 0))  # b'5'
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    8.8 居间移除

    ltrim(name, start, end) 移除区间以外的值
    start: 索引的起始位置
    end: 索引结束位置(大于列表长度, 则代表不异常任何)
    
    • 1
    • 2
    • 3
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    # -                  4  3  2  1  0
    conn.lpush('list12', 1, 2, 3, 4, 5)
    print(conn.lrange('list12', 0, -1))
    
    conn.ltrim('list12', 0, 0)
    print(conn.lrange('list12', 0, -1))  # [b'5']
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    8.9 制作生成器

    redis中没有提供列表的增量迭代, 如果想要循环name对应的列表所有元素, 需要自己定义.
    如果列表非常发, 可能会撑爆内存, 每次值取值一部分值, 使用yield放回, 制作一个生成器.
    
    • 1
    • 2
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL)
    
    # 写入数据
    conn.lpush('l1', *[1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
    
    
    # 自定义生成器
    def scan_list(name, count):
        # 定义初始值游标
        index = 0
        while True:
            data_list = conn.lrange(name, start=index, end=count + index - 1)
            # 取不值才结束
            if not data_list:
                return
    
            # 制作生成器
            for item in data_list:
                yield item
    
            # 移动游标, 每次移动count位
            index += count
    
    
    for i in scan_list('l1', 2):
        print(i)
    
    """
    b'10'
    b'9'
    
    
    b'2'
    b'1'
    """
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    9. 管道

    redis中使用管道实现事务. 要么都成功要么都失败, redis是非关系型数据库, 对事务的支持都不是很好(没有回滚).
    账单操作都是使用关系型数据库
    
    • 1
    • 2
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL, decode_responses=True)
    
    conn.set('user1', 100)
    conn.set('user2', 100)
    
    
    # transaction=True 开始事务
    pipe = conn.pipeline(transaction=True)
    pipe.multi()  # 在multi后面多条操作命令
    
    user1_money = int(conn.get('user1')) - 20
    pipe.set('user1', user1_money)
    
    user2_money = int(conn.get('user2')) + 20
    pipe.set('user2', user2_money)
    
    pipe.execute()  # 支持上面的操作命令
    
    print(conn.get('user1'))  # b'80'
    print(conn.get('user2'))  # b'120'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    10. 其他操作

    10.1 查看所有键

    keys: 查看redis中所有的键
    
    • 1
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL, decode_responses=True)
    
    print(conn.keys())  # [b'list16', b'user2', b'l1', b'user1']
    """
    可以使用通配符 * - []  
    """
    print(conn.keys('user*'))  # [b'user2', b'user1']
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    10.2 删除键

    delete(key)  删除键
    
    • 1
    from connection_pool import POOL
    
    import redis
    
    conn = redis.Redis(connection_pool=POOL, decode_responses=True)
    
    print(conn.keys())  # [b'list16', b'user2', b'l1', b'user1']
    
    print(conn.delete('user1'))  # 1
    
    print(conn.keys())  # [b'list16', b'user2', b'l1']
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    10.3 类方法生成对象

    类调用方法生成连接对象
    Redis.from_url('redis://127.0.0.1:6379/')
    
    • 1
    • 2
    import redis
    
    conn = redis.Redis.from_url('redis://127.0.0.1:6379/')
    print(conn.get('user2'))  # b'120'
    
    • 1
    • 2
    • 3
    • 4

    10.4 执行redis命令

    redis模块并没有把所有的redis命名都封装成方法, 如果没有该该方法使用execute方法去调用.
    conn.execute_command(*args命令, **options参数)
    
    • 1
    • 2
    import redis
    
    conn = redis.Redis.from_url('redis://127.0.0.1:6379/')
    print(conn.execute_command('get', 'user2'))  # b'120'
    
    • 1
    • 2
    • 3
    • 4

    10.5 判断键是否存在

    exists(name) 判断键是否存在, 存在返回1, 不会在返回0.
    
    • 1
    import redis
    
    conn = redis.Redis.from_url('redis://127.0.0.1:6379/')
    print(conn.exists('user2'))  # 1  
    print(conn.exists('user1'))  # 0
    
    • 1
    • 2
    • 3
    • 4
    • 5

    10.6 设置超时

    expire(key, timeout)  为key设置超时时间
    
    • 1
    import time
    import redis
    
    conn = redis.Redis.from_url('redis://127.0.0.1:6379/')
    print(conn.expire('user2', 1))  # Ture 设置超时时间
    print(conn.get('user2'))  # b'120'
    
    time.sleep(2)
    print(conn.get('user2'))  # None
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    10.7 重命名

    rename(src, dst) 
    src 旧名字
    dst 新名字
    
    • 1
    • 2
    • 3
    import redis
    
    conn = redis.Redis.from_url('redis://127.0.0.1:6379/', decode_responses=True)
    conn.set('l1', '我叫l1')
    print(conn.get('l1'))  # 我叫l1
    print(conn.get('l2'))  # None
    
    conn.rename('l1', 'l2')
    
    print(conn.get('l1'))  # None
    print(conn.get('l2'))  # 我叫l1
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    10.8 切换db库

    move(name, db库名)
    db库是自定生成的, 一般的不会去操作, 值是int.
    
    • 1
    • 2

    image-20220525225308814

    import redis
    
    conn = redis.Redis.from_url('redis://127.0.0.1:6379/', decode_responses=True)
    
    conn.move('l2', 1)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    image-20220525225400380

    10.9 随机获取键

    randomkey() 随机获取一个键
    
    • 1
    import redis
    
    conn = redis.Redis.from_url('redis://127.0.0.1:6379/', decode_responses=True)
    
    conn.set('k1', 'v1')
    conn.set('k2', 'v2')
    conn.set('k3', 'v3')
    
    print(conn.randomkey())  # k2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    10.10 获取键的对应值的类型

    import redis
    
    conn = redis.Redis.from_url('redis://127.0.0.1:6379/', decode_responses=True)
    
    conn.set('k1', 'v1')
    conn.set('k2', 'v2')
    conn.set('k3', 'v3')
    
    print(conn.type('k2'))  # string
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    11. Django中使用redis

    * 1. 通用方式: 使用redis模块, 生成连接对象去操作.
    * 2. django_redis模块.(继承django的cache, 使用方式进而cache的使用一致, 
    	数据被加密存到redis中, 不需要考虑数据类型.)
         1. pip install django_redis
         2. 在settings.py 配置文件中配置django_redis的信息
    
    • 1
    • 2
    • 3
    • 4
    • 5
    # CACHES 是Django的缓存配置
    CACHES = {
            # 默认配置, 可以配置多个
            "default": {
                # Django缓存使用django_redis
                "BACKEND": "django_redis.cache.RedisCache",
                # redis的地址
                "LOCATION": "redis://127.0.0.1:6379",
                # 选项
                "OPTIONS": {
                    "CLIENT_CLASS": "django_redis.client.DefaultClient",
                    # 连接池
                    "CONNECTION_POOL_KWARGS": {"max_connections": 100}
                    # 密码
                    # "PASSWORD": "123",
                }
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    image-20220526110651699

    文件夹是自动创建的...
    
    • 1
    * 3. 使用 django_redis 生成连接对象(需要考虑数据类型)
    
    • 1
    from django_from django_redis import get_redis_connection
    
    # 使用cache配置的default配置
    conn = get_redis_connection('default')
    conn.set('name', 'kid')
    
    print(conn.get('name'))  # b'kid'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  • 相关阅读:
    Apache+PHP8+MYSQL的配置(目前最新版本)
    ROS1学习笔记:创建工作环境与功能包(ubuntu20.04)
    Java,利用switch的穿透
    【LeetCode】删除有序数组中的重复项、合并两个有序数组
    Python绘制global mapping
    基于PHP+MySQL高校教务选课系统的设计与实现
    HarmonyOS的功能及场景应用
    罗丹明聚乙二醇磷脂,Rhodamine-PEG-DSPE,DSPE-PEG-Rhodamine,罗丹明PEG磷脂,磷脂PEG罗丹明,磷脂聚乙二醇罗丹明
    Debezium日常分享系列之:使用数据库中的数据流进行在线机器学习
    Android security知识点总结
  • 原文地址:https://blog.csdn.net/qq_46137324/article/details/124991470