zoukankan      html  css  js  c++  java
  • Redis

    一 Redis简介

    redis可以支持五大(字符串string、链表list、字典hash、集合set、有序集合zset)数据类型,比起Memcached来说,它只能支持一种(字符串)数据类型。redis虽然是单线程,但是效率极高,并且可以将数据持久化;相反,Memcached只能将数据暂存到内存中,断电数据就会丢失!

    二 Redis使用

    2.1 Redis安装

    下载Redis-x64-3.2.100.msi,在pycharm中安装redis模块

    • 使用命令行输入命令:pip3 install redis
    • 也可用pycharm
      1. settings,选择project下的Project Interpreter进行安装
      2. Terminal界面安装,输入命令:pip3 install redis

    2.2 Redis连接

    import redis
    
    conn = redis.Redis('127.0.0.1', 6379)
    conn.set('f1', 'hello')
    print(conn.get('f1'))
    
    # b'hello'

    注意点:redis默认的是bytes的数据类型,可以加参数设置为字符串类型,decode_responses=True

    import redis
    
    conn = redis.Redis('127.0.0.1', 6379, decode_responses=True)
    conn.set('f1', 'hello')
    print(conn.get('f1'))   # hello

    2.3 使用密码认证登陆

    1. 修改配置文件

    安装目录下的 C:Program Files (x86)Redisredis.windows-service.conf 文件,找到文件中的这一行:# requirepass foobared,去掉注释,将后面的foobared改为自己需要的密码即可!如:

    2. 重启Redis

    方法有很多,自己都可以尝试

    3. 使用密码登陆

    如果不使用密码登陆则无法操作Redis,会报一个NOAUTH的错,如:

    所以登陆时要制定密码,-a 制定自己设置好的密码,如:redis-cli -h 127.0.0.1 -p 6379 -a test

    2.4 Redis连接池

    redis使用ConnectionPool来管理对一个redis server的所有连接,避免每次建立、释放连接的开销。默认每个Redis实例都会维护一个自己的连接池。为避免重复开启连接池,可以用单例的思想实现多个Redis实例共享一个连接池

    import redis
    # 实例化
    POOL = redis.ConnectionPool()
    conn = redis.Redis(host='127.0.0.1', port=6379, connection_pool=POOL)
    conn.set('m', 'name')
    
    print(conn.get('m'))
    

    方法一:利用python的便利之处,导入模块来实现连接池的单例化

    import redis
    
    POOL = redis.ConnectionPool(host='127.0.0.1', port=6379)
    redis_test.py
    import redis
    import redis_test
    
    conn = redis.Redis(connection_pool=redis_test.POOL)
    conn.set('m', 'name')
    print(conn.get('m'))

    方法二:安装django-redis模块,然后配置、导入,实现连接池的单例化

    • 在settings.py 文件中进行如下的配置:
    CACHES = {
        "default": {
            "BACKEND": "django_redis.cache.RedisCache",
            "LOCATION": "redis://127.0.0.1:6379",
            "OPTIONS": {
                "CLIENT_CLASS": "django_redis.client.DefaultClient",
                "CONNECTION_POOL_KWARGS": {"max_connections": 100}
                # "PASSWORD": "123",
            }
        }
    }
    • 视图函数
    from django_redis import get_redis_connection
    
    
    def setname(request):
         connect = get_redis_connection()
         connect.set('name', 'bob')
         return HttpResponse('success')
    
    
    def getname(request):
        connect = get_redis_connection()
        name = connect.get('name')
        return HttpResponse(name)

    三 Redis数据类型之string

    redis中的String在内存中按照一个name对应一个value的形式来存储,如下

    import redis
    import redis_test
    
    conn = redis.Redis(connection_pool=redis_test.POOL)
    
    # set 设置值
    conn.set('name', 'value', ex=None, px=None, nx=False, xx=False)
    '''
        ex:过期时间(s)
        px:过期时间(ms)
        nx:设置为True,只有name不存在时,set操作才执行,值存在,不修改原值
        xx:设置为True,只有name存在时,set操作才执行,值不存在,不设置新值
    '''
    
    # get 取值
    conn.get('name')
    
    # mset 批量设置值,键值对的关系
    conn.mset({'key1': 'value1', 'key2': 'value2'})
    
    # mget 批量取值
    conn.mget('key1', 'key2')
    conn.mget(['key1', 'key2'])
    conn.mget(('key1', 'key2'))
    
    # strlen 返回name对应值的字节长度(一个汉字3个字节)
    conn.strlen(name='key2')
    
    # append 在key对应的值后面追加内容
    conn.append(key='key1', value='value')
    
    # incr 自增name对应的值,当name不存在时,则创建name=amount,否则,则自增
    conn.incr(name='key1', amount=1)
    '''
    name: Redis的name
    amount: 自增数(必须是整数)
    '''
    
    # decr 自减name对应的值,当name不存在时,则创建name=amount,否则,则自减
    conn.decr(name='key1', amount=1)
    '''
    name: Redis的name
    amount: 自减数(必须是整数)
    '''
    
    # setnx 设置值,只有name不存在时,执行设置操作(添加),如果存在,不会修改
    conn.setnx('name', 'jack')
    
    # setex 设置值,time,过期时间(数字秒 或 timedelta对象)
    conn.setex(name='name', time=5, value='value')
    
    # psetex 设置值,time_ms,过期时间(数字毫秒 或 timedelta对象)
    conn.psetex(name='name', time_ms=3, value='value')
    
    # getset 设置新值并获取原来的值
    conn.getset('name', 'value')
    
    # getrange 获取子序列(根据字节获取,非字符)
    conn.getrange('key1', start=0, end=4)
    '''
    start: 起始位置(字节)
    end: 结束位置(字节)
    如: "jack" ,0-4表示 "jack"
    '''
    
    # setrange 修改字符串内容,从指定字符串索引开始向后替换(新值太长时,则向后添加)
    conn.setrange(name='key', offset=1, value='value')
    '''
    offset: 字符串的索引,字节(一个汉字三个字节)
    value: 要设置的值
    '''
    string常用操作

    四 Redis数据类型之list

    redis中的List在内存中按照name对应一个List的形式来存储,如下

    import redis
    import redis_test
    
    # from django_redis import get_redis_connection
    
    # conn = get_redis_connection(alias='default')
    
    conn = redis.Redis(connection_pool=redis_test.POOL)
    
    # lpush 设置值,存入redis的顺序是倒序,取值时按照倒序存入的顺序,如下:
    conn.lpush('ll', 'bob', 'jack', 'lee')  # ll = ['lee', 'jack', 'bob']
    print(conn.lindex('ll', 2))  # b'bob'
    
    # lpushx 添加值,name存在时,会将新值添加到链表的左边
    conn.lpushx(name='ll', value='zero')  # ll = ['zero', 'lee', 'jack', 'bob']
    # name不存在时,不会新增数据,取值时会取到None
    conn.lpushx(name='lll', value='zero')
    print(conn.lindex('lll', 2))  # None
    
    # rpush 设置值,正常顺序存取
    conn.rpush('age', 12, 15, 23, 34)  # ll = [12, 15, 23, 34]
    print(conn.lindex('age', 3))  # b'34'
    
    # lpushx 添加值,name存在时,会新增数据
    conn.rpushx(name='age', value=55)  # ll = [12, 15, 23, 34, 55]
    # name不存在时,不会新增数据,取值时会取到None
    conn.rpushx(name='ages', value=66)
    print(conn.lindex('ages', 2))  # None
    
    # llen 统计链表的长度
    print(conn.llen('age'))
    
    # linsert 插入值
    conn.linsert(name='age', where='after', refvalue=23, value=111)
    # ll = [12, 15, 23, 111, 34, 55]
    '''
    name: redis的name
    where: BEFORE或AFTER(小写也可以)
    refvalue: 标杆值,即:在它前后插入数据(如果存在多个标杆值,以找到的第一个为准)
    value: 要插入的新值
    '''
    
    # lset 修改值, name、index存在时,修改原值;name或index不存在时,报错
    conn.lset(name='age', index=2, value=333)
    
    # lpop 删除数据,name存在,从左边删除一个值并返回已删除的值;name不存在,返回None
    print(conn.lpop(name='age'))  # b'12'
    
    # lrem 删除值,返回删除的数据个数, name不存在时,返回0
    print(conn.lrem(name='ll', count=2, value='jack'))  # 1
    '''
    name: redis的name
    count=0,删除列表中所有的指定值;
    count=n,从前到后删除n个,值不足n个时,有多少删除多少,并返回删除的个数
    count=-n,从后向前删除n个,值不足n个时,有多少删除多少,并返回删除的个数
    value: 要删除的值
    '''
    
    # lrange 分片取值,前闭后闭区间
    print(conn.lrange(name='age', start=1, end=3))  # [b'111', b'333', b'55']
    print(conn.lrange('age', 0, conn.llen('age')))  # [b'23', b'111', b'333', b'55']
    '''
    name: redis的name
    start: 索引的起始位置
    end: 索引结束位置 
    '''
    
    # ltrim 移除值,在name对应的列表中移除没有在start-end索引之间的值
    conn.ltrim(name='ll', start=1, end=3)
    '''
    name: redis的name
    start: 索引的起始位置
    end: 索引结束位置(大于列表长度,则代表不移除任何)
    '''
    
    # rpoplpush 从一个列表取出最右边的元素,同时将其添加至另一个列表的最左边
    print(conn.rpoplpush(src='ll', dst='age'))
    '''
    src: 要取数据的列表的name
    dst: 要添加数据的列表的name
    '''
    
    # blpop 将多个列表排列,按照从左到右的顺序去pop掉对应列表的元素
    # brpop 从右向左获取数据
    # 如果列表中没有值,会一直hang住,可实现简单的分布式
    print(conn.blpop(keys='age', timeout=3))
    '''
    keys: redis的name的集合
    timeout: 超时时间,当所有列表的元素获取完之后,阻塞等待列表内有数据的时间(秒), 0 表示永远阻塞
    '''
    # 爬虫实现简单分布式:多个url放到列表里,往里不停放URL,程序循环取值,但是只能一台机器运行取值,可以把url放到redis中,多台机器从redis中取值,爬取数据,实现简单分布式
    list常用操作
    • 自定义增量迭代
    # 自定义增量迭代
    conn.lpush('test', *[1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 43, 45, 56, 68, 89, 99, 65, 94, 23, 54, 57, 88, 68])
    
    
    def list_iter(name, count=2):
        index = 0
        while True:
            list_data = conn.lrange(name, index, index + count - 1)
            if not list_data:
                return
            index += count
            for iter in list_data:
                yield iter
    
    
    print(conn.lrange('test', 0, 100))
    # [b'68', b'88', b'57', b'54', b'23', b'94', b'65', b'99', b'89', b'68', b'56', b'45', b'43', b'9', b'8', b'7', b'6', b'5', b'5', b'4', b'3', b'2', b'1']
    for i in list_iter('test'):
        print('---------------')
        print(i)

    五 Redis数据类型之hash

    redis中的Hash在内存中的存储格式,如下

    import redis
    import redis_test
    
    conn = redis.Redis(connection_pool=redis_test.POOL)
    
    # hset 设置值
    # name对应的hash中设置一个键值对(不存在,则创建;否则,修改)
    conn.hset('mm', 'name', 'bob')
    # hsetnx(name, key, value),当name对应的hash中不存在当前key时则创建(相当于添加)
    
    # hget 取值
    conn.hget('mm', 'key')
    
    # hmset 批量设置值,键值对的关系
    conn.hmset('mm', {'name': 'bob', 'age': 18})
    
    # hmget 批量取值
    conn.hmget('mm', 'key1', 'key2')
    conn.hmget('mm', ['key1', 'key2'])
    conn.hmget('mm', ('key1', 'key2'))
    
    # hlen 返回name对应的键值对的个数
    conn.hlen(name='mm')
    
    # hkeys 获取name对应的hash中所有的key的值
    conn.hkeys(name='mm')
    
    # hvals 获取name对应的hash中所有的value的值
    conn.hvals(name='mm')
    
    # hexists 检查name对应的hash是否存在当前传入的key
    conn.hexists(name='mm', key='name')
    
    # hdel 将name对应的hash中指定key的键值对删除
    conn.hdel('mm', 'name')
    
    # hgetall 获取name对应hash的所有键值,拿到的是字典类型
    conn.hgetall(name='mm')
    
    # hincrby 自增name对应的hash中的指定key的值,不存在则创建key=amount
    conn.hincrby(name='mm', key='age', amount=1)
    '''
    name,redis中的name
    key, hash对应的key
    '''
    
    # hscan 增量式迭代取值,hscan可以实现分片的获取数据,并非一次性将数据全部获取完,而使内存爆满
    conn.hscan(name='mm', cursor=0, match=None,count=None)
    '''
    cursor: 游标(基于游标分批取获取数据)
    match: 匹配指定key,默认None 表示所有的key
    count: 每次分片后最少取值的个数,默认None
    '''
    
    # hscan_iter 利用yield封装hscan创建生成器,实现分批去redis中获取数据
    conn.hscan_iter(name='mm', match=None, count=None)
    '''
    match: 匹配指定key,默认None 表示所有的key
    count: 每次分片最少获取个数,默认None表示采用Redis的默认分片个数
    '''
    hash常用操作
  • 相关阅读:
    Centos 下查看服务器CPU的信息
    网速的一些知识整理
    如何复制文件夹里面的全部内容? 在pc上
    DataGridView中CellClick的使用,选中一行触发的动作可以在这个方法里执行
    C# 文件的压缩与解压缩
    C#调用Exe 及 有参数的
    oracle提示 ORA12154: TNS: 无法解析指定的连接标识符 OCIEnvCreate 失败, 返回代码为1,但错误消息文本不可用
    C# 导出wps配置服务器 注意事项
    C# FTP 操作类
    组件服务问题
  • 原文地址:https://www.cnblogs.com/rongge95500/p/10191421.html
Copyright © 2011-2022 走看看