zoukankan      html  css  js  c++  java
  • 一 python+redis使用(字典 列表)

    一  .redis+python操作

    1.redis

    redis.windows.conf各项配置参数介绍     win版             https://www.cnblogs.com/xuchunlin/p/7097729.html

    https://www.cnblogs.com/zhaohuhu/p/9140673.html#_label0_0

    https://www.runoob.com/redis/redis-sorted-sets.html

    https://www.cnblogs.com/wupeiqi/articles/5132791.html

    Redis是一个开源(BSD许可),内存数据结构存储,用作数据库,缓存和消息代理。
    它支持数据结构,如 字符串,散列,列表,集合,带有范围查询的排序集,位图,超级日志和带有半径查询的地理空间索引。
    Redis具有内置复制,Lua脚本,LRU驱逐,事务和不同级别的磁盘持久性,并通过Redis Sentinel提供高可用性和Redis 
    Cluster自动分区。

    用于操作内存的软件
    可以做持久化
    AOF
    RDB
    -相当于一个大字典
    单进程单线程

    redis常见性能问题和解决方案:


    (1) Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件 (2) 如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次 (3) 为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内 (4) 尽量避免在压力很大的主库上增加从库 (5) 主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1 <- Slave2 <- Slave3... 这样的结构方便解决单点故障问题,实现Slave对Master的替换。如果Master挂了,可以立刻启用Slave1做Master,其他不变。

     2. resis+python

    1. 连接池

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

    使用连接池
    本质 维护一个已经和服务器连接成功了的socket
    以后再发送数据时 直接获取一个sockect 直接send数据
    import redis pool = redis.ConnectionPool(host='192.168.18.11', port=6379) r = redis.Redis(connection_pool=pool) r.set('foo', 'Bar') print (r.get('foo')) #是一个字节 b'Bar'

     2. redis字典操作(注意:redis操作时 只有第一层value支持 list dict..)

    https://www.cnblogs.com/xuchunlin/p/7064860.html

    redis支持五大数据类型,只支持第一层,也就说字典的value值,必须是字符串
    如果value值想存字典,必须用json转换一下,转成字符串

    import redis
    pool = redis.ConnectionPool(host='localhost', port=6379)
    conn= redis.Redis(connection_pool=pool)
    
    # 字典操作  
    """resds={
           k1:{
               username:nice,
               age:18
           }
    }"""
    
    # 设置值
    conn.hset("k1","username","nice")
    conn.hset("k1","age",18)
    redis hash字典操作

    reids:{ k1:
    'dafdadfasf', m1:{ 'key2':value2, 'key1':value1, } }
    hset(name, key, value),插入值

    #
    name对应的hash中设置一个键值对(不存在,则创建;否则,修改) # 参数: # name,redis的name # key,name对应的hash中的key # value,name对应的hash中的value # 注: # hsetnx(name, key, value),当name对应的hash中不存在当前key时则创建(相当于添加) # 设置值 # conn.hset('m1','cao','曹蕊')
    hmset(name, mapping),批量插入值

    #
    在name对应的hash中批量设置键值对 # 参数: # name,redis的name # mapping,字典,如:{'k1':'v1', 'k2': 'v2'} # 如: # r.hmset('xx', {'k1':'v1', 'k2': 'v2'}) # 批量插入设置值 # conn.hmset('m2', {'cao': 100, 'bai': 101})
     hget(name,key),取值

    #
    在name对应的hash中获取根据key获取value # 取值,根据大字典的key,再去查key print(conn.hget('m2','cao'))
    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') print(conn.hmget('m2','cao','bai')) print(conn.hmget('m2',['cao','bai']))
    hlen(name)

    #
    获取name对应的hash中键值对的个数 # print(conn.hlen('m2'))
    hkeys(name)

    #
    获取name对应的hash中所有的key的值 # print(conn.hkeys('m2'))
    hvals(name)

    #
    获取name对应的hash中所有的value的值 # print(conn.hvals('m2'))
    hexists(name, key)

    #
    检查name对应的hash是否存在当前传入的key # print(conn.hexists('m2','cao'))
    hdel(name,*keys)

    #
    将name对应的hash中指定key的键值对删除 print(re.hdel('xxx','sex','name')) # conn.hdel('m2','key1','key2') # 这样可以 # conn.hdel('m2',*['key1','key2']) # 这样不行 # conn.hdel('m2',['key1','ke
    hincrby用来统计一个东西的数量的频繁增加(name, key, amount=1)  计数器

    hincrby应用场景: 统计文章阅读数:key是文章id,value是文章阅读数,有一个阅读者,数字加一,固定一个时间,将数据同步到数据库,
    一定要写日志,避免出错,还能查找到
    # 自增name对应的hash中的指定key的值,不存在则创建key=amount # 参数: # name,redis中的name # key, hash对应的key # amount,自增数(整数) conn.hincrby('m1','key3')
    hincrbyfloat(name, key, amount=1.0)

    #
    自增name对应的hash中的指定key的值,不存在则创建key=amount # 参数: # name,redis中的name # key, hash对应的key # amount,自增数(浮点数) # 自增name对应的hash中的指定key的值,不存在则创建key=amount
    hgetall(name)——慎用,一次性取出数据前需要先hlen看下长度

    #
    获取name对应hash的所有键值 print(re.hgetall('xxx').get(b'name')) # 根据key把所有的值取出来 # print(conn.hgetall('m2'))
    
    
    hscan_iter(name, match=None, count=None),增量迭代取值

    #
    利用yield封装hscan创建生成器,实现分批去redis中获取数据 # 参数: # match,匹配指定key,默认None 表示所有的key # count,每次分片最少获取个数,默认None表示采用Redis的默认分片个数 # 如: # for item in r.hscan_iter('xx'): # print item 应用场景: 比如我redis中字典有10000w条数据,全部都打印出来 hscan——指定游标,然后取多少值 for i in range(1000): conn.hset('m2','key%s'%i,'value%s'%i) 指定每次取10条,直到取完 ret=conn.hscan_iter('m2',count=100) 不要用这种方式,一下全部取出,redis可能会被撑爆,或者先用len查看下长度再决定使用getall或者其他 ret=conn.hgetall('m2')
    hscan(name, cursor=0, match=None, count=None)——指定游标,然后取多少数据

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

    3. redis列表操作(队列:先进先出    栈:后进先出)

    https://www.cnblogs.com/zl1991/p/10552160.html

     
    import redis
    pool = redis.ConnectionPool(host='localhost', port=6379)
    conn= redis.Redis(connection_pool=pool)
    """
    redis = {
    
        k1:[1,2,3,43,45]
    }
    """
    conn.lpush('k1',1111)
    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,要插入的数据
    
    
    
    r.lset(name, index, value)
    # 对name对应的list中的某一个索引位置重新赋值
    # 参数:
        # name,redis的name
        # index,list的索引位置
        # value,要设置的值
    
    
    
    r.lrem(name, value, num)
    # 在name对应的list中删除指定的值
    # 参数:
        # name,redis的name
        # value,要删除的值
        # num,  num=0,删除列表中所有的指定值;
               # num=2,从前到后,删除2个;
               # num=-2,从后向前,删除2个
    
    
    
    lpop(name)
    # 在name对应的列表的左侧获取第一个元素并在列表中移除,返回值则是第一个元素
     
    # 更多:
        # rpop(name) 表示从右向左操作
    
    
    
    lindex(name, index)
    在name对应的列表中根据索引获取列表元素
    
    
    
    lrange(name, start, end)
    # 在name对应的列表分片获取数据
    # 参数:
        # name,redis的name
        # start,索引的起始位置
        # end,索引结束位置
    
    
    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),从右向左获取数据

    brpoplpush(src, dst, timeout
    =0) # 从一个列表的右侧移除一个元素并将其添加到另一个列表的左侧 # 参数: # src,取出并要移除元素的列表对应的name # dst,要插入元素的列表对应的name # timeout,当src对应的列表中没有数据时,阻塞等待其有数据的超时时间(秒),0 表示永远阻塞
    自定义增量迭代    (- 通过yield创建一个生成器完成一点一点获取   通过字典操作的源码来的灵感)

      由于redis类库中没有提供对列表元素的增量迭代,如果想要循环name对应的列表的所有元素,那么就需要:
        # 1、获取name对应的所有列表
        # 2、循环列表
         # 但是,如果列表非常大,那么就有可能在第一步时就将程序的内容撑爆,所有有必要自定义一个增量迭代的功能:
     
    import redis
    conn = redis.Redis(host='47.94.172.250',port=6379,)
    
    def list_iter(key,count=100):
         自定义redis列表增量迭代
        :param name: redis中的name,即:迭代name对应的列表
        :return: yield 返回 列表元素
        index = 0
        while True:
            data_list = conn.lrange('k1', index, index+count-1)
            if not data_list:
                return
            index += count
            for item in data_list:
                yield item
    
    print(conn.lrange('k1',0,101))


    使用
    for item in list_iter('k1',count=3): print(item)
    - 事务+一次发送多个命令

    conn = redis.Redis(host='47.94.172.250',port=6379) pipe = conn.pipeline(transaction=True) pipe.multi() pipe.set('k2','123') pipe.hset('k3','n1',666) pipe.lpush('k4','laonanhai') pipe.execute()
  • 相关阅读:
    MongoDB 释放磁盘空间 db.runCommand({repairDatabase: 1 })
    RK 调试笔记
    RK Android7.1 拨号
    RK Android7.1 移植gt9271 TP偏移
    RK Android7.1 定制化 itvbox 盒子Launcher
    RK Android7.1 双屏显示旋转方向
    RK Android7.1 设置 内存条作假
    RK Android7.1 设置 蓝牙 已断开连接
    RK Android7.1 进入Camera2 亮度会增加
    RK 3128 调触摸屏 TP GT9XX
  • 原文地址:https://www.cnblogs.com/lovershowtime/p/11714760.html
Copyright © 2011-2022 走看看