zoukankan      html  css  js  c++  java
  • Redis

    Redis

    一、什么是redis

    redis是一个key-value存储系统

    二、redis的作用

    1、查询速度快:把数据存储到内存中

    2、不需要提交定义好字段

    三、NoSQL分类

    1. memcache
    - 数据存放到内存, 不能落地、持久化,数据断电就没了
    - 支持数据类型太少,只支持字符串
    
    2. MongoDB
    - 数据存放到内存, 解决了数据的持久化
    - 支持多种数据类型
    
    3. redis
    - 数据存放到内存,可以把数据持久化到硬盘,解决了数据的持久化
    - 支持5大数据类型格式:string(字符串)、list(链表)、set(集合)、zset(有序集合)、hash(字典、哈希类型)
    - 单线程
    

    四、Python操作redis

    1、安装模块

    pip3 install redis
    

    2、基本使用

    import redis
    
    conn = redis.Redis(host='localhost', port=6379)  # host与port有默认值
    conn.set('m','string')
    
    

    五、操作string

    set(name, value, ex=None, px=None, nx=False, xx=False)

    在Redis中设置值,默认,不存在则创建,存在则修改
    参数:
         ex,过期时间(秒)
         px,过期时间(毫秒)
         nx,如果设置为True,则只有name不存在时,当前set操作才执行,值存在,就修改不了,执行没效果
         xx,如果设置为True,则只有name存在时,当前set操作才执行,值存在才能修改,值不存在,不会设置新值
    
    conn.set('m1','string',ex=5)   # 5秒后过期
    

    setnx(name, value)

    # 设置值,只有name不存在时,执行设置操作(添加);如果存在,不会修改
    

    setex(name, time, value)

    # 设置过期时间(数字秒 或 timedelta对象)
    conn.setex('m',5,'string')
    

    psetex( name, time_ms, value)

    # time_ms,过期时间(数字毫秒 或 timedelta对象
    conn.setex('m',5000,'string')
    

    mset(*args, **kwargs)

    # 批量设置
    conn.mset({'m1':'v1','m2':'v2'})
    

    get(name)

    # 取值
    conn.get('m1')   # b'v1',bytes类型
    

    mget(keys, **args)

    # 批量获取
    conn.mget('k1','k2')
    

    getset(name, value)

    # 设置新值并获取原来的值
    

    getrange(key, start, end)

    # 获取子序列(根据字节获取,非字符)前闭后闭区间
    # 参数:
        # name,Redis 的 name
        # start,起始位置(字节)
        # end,结束位置(字节)
    # 如: "汤姆猫" ,0-3表示 "汤"
    conn.getrange('m1',0,3)
    print(conn.getrange('name',0,3).decode('utf-8'))
    

    setrange(name, offset, value)

    # 修改字符串内容,从指定字符串索引开始向后替换(新值太长时,则向后添加)
    # 参数:
        # offset,字符串的索引,字节(一个汉字三个字节)
        # value,要设置的值
    

    setbit(name, offset, value)

    # 对name对应值的二进制表示的位进行操作
     
    # 参数:
        # name,redis的name
        # offset,位的索引(将值变换成二进制后再进行索引)
        # value,值只能是 1 或 0
     
    # 注:如果在Redis中有一个对应: n1 = "foo",
            那么字符串foo的二进制表示为:01100110 01101111 01101111
        所以,如果执行 setbit('n1', 7, 1),则就会将第7位设置为1,
            那么最终二进制则变成 01100111 01101111 01101111,即:"goo"
    

    getbit(name, offset)

    # 获取name对应的值的二进制表示中的某位的值 (0或1)
    

    bitcount(key, start=None, end=None)

    # 获取name对应的值的二进制表示中 1 的个数
    # 参数:
        # key,Redis的name
        # start,位起始位置
        # end,位结束位置
    

    bitop(operation, dest, *keys)

    # 获取多个值,并将值做位运算,将最后的结果保存至新的name对应的值
     
    # 参数:
        # operation,AND(并) 、 OR(或) 、 NOT(非) 、 XOR(异或)
        # dest, 新的Redis的name
        # *keys,要查找的Redis的name
     
    # 如:
        bitop("AND", 'new_name', 'n1', 'n2', 'n3')
        # 获取Redis中n1,n2,n3对应的值,然后讲所有的值做位运算(求并集),然后将结果保存 new_name 对应的值中
    
    # 返回name对应值的字节长度(一个汉字3个字节)
    

    incr(name, amount=1)

    # 自增 name对应的值,当name不存在时,则创建name=amount,否则,则自增。
     
    # 参数:
        # name,Redis的name
        # amount,自增数(必须是整数)
     
    # 注:同incrby
    

    incrbyfloat( name, amount=1.0)

    # 自增 name对应的值,当name不存在时,则创建name=amount,否则,则自增。
     
    # 参数:
        # name,Redis的name
        # amount,自增数(浮点型)
    

    decr( name, amount=1)

    # 自减 name对应的值,当name不存在时,则创建name=amount,否则,则自减。
     
    # 参数:
        # name,Redis的name
        # amount,自减数(整数)
    

    append(key, value)

    # 在redis name对应的值后面追加内容
     
    # 参数:
        key, redis的name
        value, 要追加的字符串
    

    strlen(name)

    # 统计长度
    conn.strlen('m')
    

    六、操作hash

    hset(name, key, value)

    # name对应的hash中设置一个键值对(不存在,则创建;否则,修改)
     
    # 参数:
        # name,redis的name
        # key,name对应的hash中的key
        # value,name对应的hash中的value
     
    # 注:
        # hsetnx(name, key, value),当name对应的hash中不存在当前key时则创建(相当于添加)
    

    hmset(name, mapping)

    # 在name对应的hash中批量设置键值对
     
    # 参数:
        # name,redis的name
        # mapping,字典,如:{'k1':'v1', 'k2': 'v2'}
     
    # 如:
        # conn.hmset('xx', {'k1':'v1', 'k2': 'v2'})
    

    hget(name,key)

    # 在name对应的hash中获取根据key获取value
    

    hmget(name, keys, *args)

    # 在name对应的hash中获取多个key的值
     
    # 参数:
        # name,reids对应的name
        # keys,要获取key集合,如:['k1', 'k2', 'k3']
        # *args,要获取的key,如:k1,k2,k3
     
    # 如:
        # r.mget('xx', ['k1', 'k2'])
        # 或
        # print r.hmget('xx', 'k1', 'k2')
    

    hgetall(name)

    # 获取name对应hash的所有键值
    print(conn.hgetall('xxx').get(b'name'))
    

    hlen(name)

    # 获取name对应的hash中键值对的个数
    

    hkeys(name)

    # 获取name对应的hash中所有的key的值
    

    hvals(name)

    # 获取name对应的hash中所有的value的值
    

    hexists(name, key)

    # 检查name对应的hash是否存在当前传入的key
    

    hdel(name,*keys)

    # 将name对应的hash中指定key的键值对删除
    print(conn.hdel('xxx','sex','name'))
    conn.hdel('m1',*['k1','k2'])
    
    

    hincrby(name, key, amount=1)

    # 自增name对应的hash中的指定key的值,不存在则创建key=amount
    # 参数:
        # name,conndis中的name
        # key, hash对应的key
        # amount,自增数(整数)
    # 统计文章阅读数:key是文章id,value是文章阅读数,有一个阅读者,数字加一,固定一个时间,将数据同步到数据库
    

    hincrbyfloat(name, key, amount=1.0)

    # 自增name对应的hash中的指定key的值,不存在则创建key=amount
     
    # 参数:
        # name,redis中的name
        # key, hash对应的key
        # amount,自增数(浮点数)
     
    # 自增name对应的hash中的指定key的值,不存在则创建key=amount
    

    hscan(name, cursor=0, match=None, count=None)

    # 增量式迭代获取,对于数据大的数据非常有用,hscan可以实现分片的获取数据,并非一次性将数据全部获取完,从而放置内存被撑爆
     
    # 参数:
        # name,conndis的name
        # cursor,游标(基于游标分批取获取数据)
        # match,匹配指定key,默认None 表示所有的key
        # count,每次分片最少获取个数,默认None表示采用conndis的默认分片个数
     
    # 如:
        # 第一次:cursor1, data1 = conn.hscan('xx', cursor=0, match=None, count=None)
        # 第二次:cursor2, data1 = conn.hscan('xx', cursor=cursor1, match=None, count=None)
        # ...
        # 直到返回值cursor的值为0时,表示数据已经通过分片获取完毕
    

    hscan_iter(name, match=None, count=None)

    # 利用yield封装hscan创建生成器,实现分批去redis中获取数据
     
    # 参数:
        # match,匹配指定key,默认None 表示所有的key
        # count,每次分片最少获取个数,默认None表示采用Redis的默认分片个数
     
    # 如:
        for item in conn.hscan_iter('xx',count=100):
        	print(item)
    
    # hscan_iter源码
        def hscan_iter(self, name, match=None, count=None):
            cursor = '0'
            while cursor != 0:
                cursor, data = self.hscan(name, cursor=cursor,
                                          match=match, count=count)
                for item in data.items():
                    yield item
    

    七、操作list

    lpush(name,values)

    # 在name对应的list中添加元素,每个新的元素都添加到列表的最左边
     
    # 如:
        # r.lpush('oo', 11,22,33)
        # 保存顺序为: 33,22,11
     
    # 扩展:
        # rpush(name, values) 表示从右向左操作
    

    lpushx(name,value)

    # 在name对应的list中添加元素,只有name已经存在时,值添加到列表的最左边
     
    # 更多:
        # rpushx(name, value) 表示从右向左操作
    

    llen(name)

    # name对应的list元素的个数
    

    linsert(name, where, refvalue, value))

    # 在name对应的列表的某一个值前或后插入一个新值
     
    # 参数:
        # name,redis的name
        # where,BEFORE或AFTER(小写也可以)
        # refvalue,标杆值,即:在它前后插入数据(如果存在多个标杆值,以找到的第一个为准)
        # value,要插入的数据
        
    # 如果有多个相同的元素,选择最左边的元素,对其的前后操作
    conn.linsert('l1','before',12,777)
    conn.linsert('l1','after',22,666)
    

    lset(name, index, value)

    # 对name对应的list中的某一个索引位置重新赋值
     
    # 参数:
        # name,redis的name
        # index,list的索引位置
        # value,要设置的值
    

    lrem(name, count, value)

    # 在name对应的list中删除指定的值
     
    # 参数:
        # name,redis的name
        # value,要删除的值
        # count,  count=0,删除列表中所有的指定值;
              	 # count=2,从前到后,删除2个;
                 # count=-2,从后向前,删除2个
    

    lpop(name)

    # 在name对应的列表的左侧获取第一个元素并在列表中移除,返回值则是第一个元素
     
    # 更多:
        # rpop(name) 表示从右向左操作
    

    lindex(name, index)

    # 在name对应的列表中根据索引获取列表元素
    

    lrange(name, start, end)

    # 在name对应的列表分片获取数据
    # 参数:
        # name,redis的name
        # start,索引的起始位置
        # end,索引结束位置  print(re.lrange('aa',0,re.llen('aa')))
    

    ltrim(name, start, end)

    # 在name对应的列表中移除没有在start-end索引之间的值
    # 参数:
        # name,redis的name
        # start,索引的起始位置
        # end,索引结束位置(大于列表长度,则代表不移除任何)
    

    rpoplpush(src, dst)

    # 从一个列表取出最右边的元素,同时将其添加至另一个列表的最左边
    # 参数:
        # src,要取数据的列表的name
        # dst,要添加数据的列表的name
    

    blpop(keys, timeout)

    # 将多个列表排列,按照从左到右去pop对应列表的元素
     
    # 参数:
        # keys,redis的name的集合
        # timeout,超时时间,当元素所有列表的元素获取完之后,阻塞等待列表内有数据的时间(秒), 0 表示永远阻塞
     
    # 更多:
        # r.brpop(keys, timeout),从右向左获取数据
    爬虫实现简单分布式:多个url放到列表里,往里不停放URL,程序循环取值,但是只能一台机器运行取值,可以把url放到redis中,多台机器从redis中取值,爬取数据,实现简单分布式
    

    brpoplpush(src, dst, timeout=0)

    # 从一个列表的右侧移除一个元素并将其添加到另一个列表的左侧
     
    # 参数:
        # src,取出并要移除元素的列表对应的name
        # dst,要插入元素的列表对应的name
        # timeout,当src对应的列表中没有数据时,阻塞等待其有数据的超时时间(秒),0 表示永远阻塞
    
    • 自定义增量迭代
    def l_iter(name, count):
        cursor = 0
        while True:
            li = conn.lrange(name, cursor, cursor + count - 1)
            if not li:
                return
            cursor += count
            for item in li:
                yield item
    
    
    ret = l_iter('t', 100)
    for r in ret:
        print(r)
    

    八、Python操作Redis之连接池

    redis-py使用connection pool来管理对一个redis server的所有连接,避免每次建立、释放连接的开销。默认,每个Redis实例都会维护一个自己的连接池。可以直接建立一个连接池,然后作为参数Redis,这样就可以实现多个Redis实例共享一个连接池

    import redis
    
    pool = redis.ConnectionPool(host='127.0.0.1', port=6379,max_connections=1000)
    r = redis.Redis(connection_pool=pool)
    

    九、Django中使用Redis

    1、方式一(在其它web框架也可以使用)

    redis-py使用connection pool来管理对一个redis server的所有连接,避免每次建立、释放连接的开销。默认,每个Redis实例都会维护一个自己的连接池。可以直接建立一个连接池,然后作为参数Redis,这样就可以实现多个Redis实例共享一个连接池
    
    

    utils文件夹下,建立redis_pool.py

    import redis
    # 建立一个连接池
    POOL = redis.ConnectionPool(host='127.0.0.1', port=6379,password='1234',max_connections=1000)
    

    视图函数中使用:

    import redis
    from django.shortcuts import render,HttpResponse
    from utils.redis_pool import POOL
    
    def index(request):
        # 从连接池中取一个连接
        conn = redis.Redis(connection_pool=POOL)
        conn.hset('kkk','age',18)
    
        return HttpResponse('设置成功')
    def order(request):
        conn = redis.Redis(connection_pool=POOL)
        conn.hget('kkk','age')
    
        return HttpResponse('获取成功')
    

    2、方式二

    使用django-redis模块

    (1)安装django-redis

    pip3 install django-redis
    
    

    (2)使用

    # 视图中
    from django_redis import get_redis_connection
    
    def setname(request):
        # 获取一个连接
        conn=get_redis_connection()
        conn.set('name', '测试')
        return HttpResponse('设置成功')
    
  • 相关阅读:
    数据驱动编程法
    23个设计模式的简明教程
    分享一篇文章C语言字节对齐问题(适用于C++)转载至http://blog.csdn.net/21aspnet/article/details/6729724
    关于C++类中访问权限的若干疑问(虚函数访问权限)
    利用C# 反射设计支持可扩展插件的应用程序
    隐藏控制台console application窗口
    Intellij IDEA社区版上新建项目或模块没有Spring Initializr选项解决办法
    mac jmeter 界面乱码
    windows 查看端口被占用进程
    php static 变量声明
  • 原文地址:https://www.cnblogs.com/linagcheng/p/10181776.html
Copyright © 2011-2022 走看看