• redis一览


    redis一览

    Redis 简介

    Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库。

    Redis 与其他 key - value 缓存产品有以下三个特点:

    • Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
    • Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
    • Redis支持数据的备份,即master-slave模式的数据备份。

    Redis 优势

    • 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
    • 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
    • 原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
    • 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。

    1、安装redis

    Redis与其他key-value存储有什么不同?

      • Redis有着更为复杂的数据结构并且提供对他们的原子性操作,这是一个不同于其他数据库的进化路径。Redis的数据类型都是基于基本数据结构的同时对程序员透明,无需进行额外的抽象。

      • Redis运行在内存中但是可以持久化到磁盘,所以在对不同数据集进行高速读写时需要权衡内存,因为数据量不能大于硬件内存。在内存数据库方面的另一个优点是,相比在磁盘上相同的复杂的数据结构,在内存中操作起来非常简单,这样Redis可以做很多内部复杂性很强的事情。同时,在磁盘格式方面他们是紧凑的以追加的方式产生的,因为他们并不需要进行随机访问。

    Window 下安装

    下载地址:https://github.com/MSOpenTech/redis/releases

    下载的为.msc后缀的,只需一顿下一步即可!

    目前只是将redis安装在win环境下的,因为现在的对linux不是很熟悉!

    2、Python操作redis

    1 pip3 install redis

    a、创建连接

    1、普通连接
    1 import redis
    2 
    3 
    4 conn = redis.Redis(host='127.0.0.1', port=6379)
    5 conn.set('animal', 'cat')
    6 val = conn.get('animal')
    7 print(val)
    2、基于连接池
    1 import redis
    2 
    3 POOL = redis.ConnectionPool(host='127.0.0.1', port=6379, max_connections=1000)    # 创建连接池
    4 conn = redis.Redis(connection_pool=POOL)
    5 
    6 conn.set("key", "cat")
    7 val = conn.get("key")
    8 print(val)

    b、redis常用操作

    在涉及到操作之前可以先来了解下redis支持的数据结构
    1. String:字符串
    2. Hash:散列(字典)
    3. List:列表
    4. Set:集合(去重)
    5. Sorted Set:有序集合
    1 # redis 就相当与内存中的一个字典。(session??)
    2 redis = {
    3     k1: 'hello',                                            # String
    4     k2: [1, 2, 3, 5, 4, 5, 2],                              # List
    5     k3: {1, 2, 3, 4},                                       # Set
    6     k4: {name: 'pontoon', age: 19},                         # Dict/Hash
    7     k5: {('pontoon': 65), ('god_v': 75), ('dandy': 85)}     # SortedSet
    8 }
    1、字典的操作
     
     1 import redis
     2 
     3 POOL = redis.ConnectionPool(host='127.0.0.1', port=6379, max_connections=1000)
     4 conn = redis.Redis(connection_pool=POOL)
     5 
     6 # conn.set("key", "cat")
     7 # val = conn.get("key")
     8 # print(val)
     9 
    10 # 1、hset(name, key, value)    # 设置单个值
    11 conn.hset("k1", "animal", "dog")
    12 
    13 # 2、hget(name,key)            # 取单个值
    14 val = conn.hget("k1", "animal")
    15 print(val)    # b'dog'  
    16 
    17 # 3、hmset(name, mapping)      # 设置多个值
    18 conn.hmset("k2", {"animal1": "cat", "animal2": "dog"})
    19 
    20 # 4、hmger(name, keys, *args)  # 取多个值
    21 val = conn.hmget("k2", "animal1", "animal2")
    22 print(val)    # [b'cat', b'dog']
    23 
    24 # 5、hgetall(name)             # 获取name对应的所有值
    25 val = conn.hgetall("k2")
    26 print(val)    # {b'animal1': b'cat', b'animal2': b'dog'}
    27 
    28 # 6、hlen(name)                # 获取个数
    29 val = conn.hlen("k2")
    30 print(val)    # 2
    31 
    32 # 7、hkeys(name)               # 获取key
    33 
    34 # 8、hvals(name)               # 获取value
    35 
    36 # 9、hexists(name, key)        # 判断是否存在
    37 val = conn.hexists("k2", "animal1")
    38 print(val)    # True
    39 
    40 # 10、hdel(name,*keys)         # 删除指定key中的键值对
    41 
    42 # 11、hincrby(name, key, amount=1)  # 自增name对应的hash中的指定key的值,不存在则创建key=amount
    43 
    44 # 12、hscan(name, cursor=0, match=None, count=None)
    45 """
    46     增量式迭代获取,对于数据大的数据非常有用,hscan可以实现分片的获取数据,并非一次性将数据全部获取完,从而放置内存被撑爆
    47     参数:
    48         name,redis的name
    49         cursor,游标(基于游标分批取获取数据)
    50         match,匹配指定key,默认None 表示所有的key
    51         count,每次分片最少获取个数,默认None表示采用Redis的默认分片个数
    52      如:
    53         第一次:cursor1, data1 = r.hscan('xx', cursor=0, match=None, count=None)
    54         第二次:cursor2, data1 = r.hscan('xx', cursor=cursor1, match=None, count=None)
    55         ...
    56         直到返回值cursor的值为0时,表示数据已经通过分片获取完毕
    57 """
    58 
    59 # 13、hscan_iter(name, match=None, count=None)
    60 """
    61     利用yield封装hscan创建生成器,实现分批去redis中获取数据
    62     
    63     参数:
    64         match,匹配指定key,默认None 表示所有的key
    65         count,每次分片最少获取个数,默认None表示采用Redis的默认分片个数
    66     
    67      如:
    68         for item in r.hscan_iter('xx'):
    69             print item
    70 """
    redis字典的操作

    关于第13条的一个补充:

    1 # 对于13的补充:
    2 假设redis中有name=k4的一个字典,这个字典中有10个G的数据,我们该如何取值?
    3 ret = conn.hscan_iter("k4", count=10000)  # 创建一个生成器对象,每次取1W条数据
    4 for i in range(1000):    1000x10000 ≈ 10G
    5     for item in ret:
    6         print(item)

    hscan_iter的源码

     1   def hscan_iter(self, name, match=None, count=None):
     2         """
     3         Make an iterator using the HSCAN command so that the client doesn't
     4         need to remember the cursor position.
     5 
     6         ``match`` allows for filtering the keys by pattern
     7 
     8         ``count`` allows for hint the minimum number of returns
     9         """
    10         # cursor表示游标 指明了count就相当于指明了cursor的数量
    11         cursor = '0'
    12         # 假如count=10000, 那么下一次迭代cursor='10000'
    13         while cursor != 0:
    14             cursor, data = self.hscan(name, cursor=cursor, match=match, count=count)
    15             for item in data.items():
    16                 yield item
    2、列表的操作

     1 import redis
     2 
     3 
     4 pool = redis.ConnectionPool(host='127.0.0.1', port=6379, max_connections=1000)  # 设置最大连接数量为1000
     5 conn = redis.Redis(connection_pool=pool)  # 连接连接池
     6 
     7 # 1、lpush(name,values)     # 列表的左侧添加数据
     8 
     9 # 2、rpush(name, values)    # 列表的右侧添加数据
    10 conn.lpush("l1", "v1")
    11 conn.lpush("l1", "v2")
    12 conn.rpush("l1", "v3")
    13 
    14 ret = conn.lrange("l1", 0, 100)  # 范围取值,取前100条数据
    15 print(ret)  # [b'v2', b'v1', b'v3']
    16 
    17 # 3、lpushx(name, value)    # 当name存在时,向列表左侧添加数据
    18 
    19 # 4、rpushx(name, value)    # 当name存在时,向列表右侧添加数据  
    20 
    21 # 5、lpop(name)             # 列表的左侧弹出数据
    22 
    23 # 6、rpop(name)             # 列表的右侧弹出数据
    24 val = conn.lpop("l1")
    25 print(val)  # b'v1'
    26 
    27 val = conn.rpop("l1")
    28 print(val)  # b'v3'
    29 
    30 
    31 # 7、llen(name)             # name对应的list元素的个数
    32 
    33 # 8、linsert(name, before/after, refvalue, value))    # 在name对应的列表的某一个值前或后插入一个新值
    34 conn.linsert("l1", "before", "v2", "v3")  # 在列表内找到第一个元素v2,在它前面插入v3
    35 
    36 ret = conn.lrange("l1", 0, 100)
    37 print(ret)
    38 
    39 # 9、lset(name, index, value)  # 对list中的某一个索引位置重新赋值
    40 conn.lset("l1", 0, "v4")  # 将索引为0的值重新赋值v4
    41 
    42 ret = conn.lrange("l1", 0, 100)
    43 print(ret)
    44 
    45 # 10、lrem(name, num, value)  
    46 ''' 参数:
    47     name:  redis的name   
    48     num:   num=0 删除列表中所有的指定值;
    49            num=2 从前到后,删除2个;
    50            num=-2 从后向前,删除2个
    51     value: 要删除的值       
    52 '''
    53 # 这里要注意lrem在最新版本的redis中用法改了,将num与value调换位置了。(难怪我对着网上的博客写一致会报错~)
    54 
    55 # 11、ltrim(name, start, end)  # 在name对应的列表中移除没有在start-end索引之间的值
    56 conn.ltrim("l1", 0, 0)  # 移除第一个之后的所有值
    57 
    58 ret = conn.lrange("l1", 0, 100)
    59 print(ret)
    60 
    61 # 12、rpoplpush(src, dst)  # 从一个列表取出最右边的元素,同时将其添加至另一个列表的最左边
    62 """
    63 参数:
    64     src,要取数据的列表的name
    65     st,要添加数据的列表的name
    66 """
    67 conn.lpush("l2", '11', '22', '33')
    68 conn.lpush("l3", '44', '55', '66')
    69 conn.rpoplpush("l2", "l3")
    70 
    71 ret = conn.lrange("l3", 0, 100)
    72 print(ret)
    73 
    74 # redis都是玩的一些什么操作啊?花里胡哨~还有一部分反向操作的就不列出来了。要吐血了
    redis列表的操作
     3、集合的操作 
     
     1 # 1、sadd(name,values)      # ame对应的集合中添加元素
     2 
     3 # 2、smembers(name)         # 获取name对应的集合的所有成员
     4 pool = redis.ConnectionPool(host='127.0.0.1', port=6379, max_connections=1000)  # 设置最大连接数量为1000
     5 conn = redis.Redis(connection_pool=pool)  # 连接连接池
     6 
     7 conn.sadd("s1", "v1")
     8 conn.sadd("s1", "v1", "v2", "v3", "v4", "v5")
     9 
    10 print(conn.smembers("s1"))
    11 >>>{b'v4', b'v5', b'v2', b'v1', b'v3'}    # 得到一个无序集合
    12 
    13 3、scard(name)              # 获取name对应的集合中的元素个数
    14 
    15 4、sdiff(keys, *args)       # 在第一个name对应的集合中且不在其他name对应的集合的元素集合(差集)
    16 conn.sadd("s2", "aa", "bb")
    17 conn.sadd("s3", "bb", "cc")
    18 conn.sadd("s4", "bb", "cc", "dd")
    19 
    20 print(conn.sdiff("s2", "s3", "s4"))  
    21 >>>{b'aa'}
    22 
    23 5、sinter(keys, *args)      # 获取多个name对应集合的交集
    24 conn.sadd("s2", "aa", "bb")
    25 conn.sadd("s3", "bb", "cc")
    26 conn.sadd("s4", "bb", "cc", "dd")
    27 
    28 print(conn.sinter("s2", "s3", "s4"))
    29 >>>{b'bb'}
    30 
    31 6、sinterstore(dest, keys, *args)  # 获取两个name对应集合的交集,并将结果存入第三个集合中
    32 conn.sadd("s3", "bb", "cc")
    33 conn.sadd("s4", "bb", "cc", "dd")
    34 
    35 print(conn.sinterstore("s2", "s3", "s4"))  # s2为一个空的store存储s3,s4的交集,返回数字
    36 print(conn.smembers("s2"))  # 返回集合中的值
    37 
    38 7、sunion(keys, *args)      # 并集,获取多个name对应的集合的并集
    39 
    40 8、smove(src, dst, value)
    41 conn.smove("s2", "s3", 'aa')
    42 print(conn.smembers("s3"))
    43 >>>{b'cc', b'aa', b'bb'}
    44 
    45 9、sismember(name, value)   # 判断是否是集合的成员 类似in
    46 
    47 10、spop(name)              # 删除--随机删除并且返回被删除值
    48 
    49 11、srem(name, values)      # 删除--指定值删除  
    50 
    51 # 集合的操作相对最简单。      
    View Code
    3.1、有序集合的操作
     1 # 注意我的redis版本为3.2.1,python在操作有序集合中的部分源码已经改了,网上的一些博客抄来抄去,自己也不动手实践下,错的地方都一样。
     2 
     3 1、zadd(name, mapping, nx=False, xx=False, ch=False, incr=False)  # zadd的源码改了,网上大部分的博客都是旧的。所以输出的时候会报错
     4 pool = redis.ConnectionPool(host='127.0.0.1', port=6379, max_connections=1000)  # 设置最大连接数量为1000
     5 conn = redis.Redis(connection_pool=pool)  # 连接连接池
     6 
     7 conn.zadd("z1", {"v11": 1, "v2": 2})
     8 print(conn.zrange("z1", 0, -1))   # 获取有序集合中所有元素
     9 >>>[b'v11', b'v2']  # 返回一个列表
    10 
    11 2、zcard(name)                  # 获取name对应的有序集合元素的数量
    12 print(conn.zcard("z1"))
    13 >>>2
    14 
    15 3、zcount(name, min, max)       # 获取name对应的有序集合中分数 在 [min,max] 之间的个数 
    16 
    17 4、zrange( name, start, end, desc=False, withscores=False, score_cast_func=float)  # 按照索引范围获取name对应的有序集合的元素
    18 """
    19 参数:
    20     name,redis的name
    21     start,有序集合索引起始位置(非分数)    # 注意是索引
    22     end,有序集合索引结束位置(非分数)
    23     desc,排序规则,默认按照分数从小到大排序
    24     withscores,是否获取元素的分数,默认只获取元素的值
    25     score_cast_func,对分数进行数据转换的函数
    26 """
    27 
    28 4.1、zrevrange(name, start, end, withscores=False, score_cast_func=float)  # 从大到小排序(同zrange,集合是从大到小排序的)
    29 4.2、zrangebyscore(name, min, max, start=None, num=None, withscores=False, score_cast_func=float)  # 按照分数范围获取name对应的有序集合的元素
    30 4.3、zrevrangebyscore(name, max, min, start=None, num=None, withscores=False, score_cast_func=float)  # 按照分数范围获取有序集合的元素并排序(默认从大到小排序)
    31 
    32 5、zscan(name, cursor=0, match=None, count=None, score_cast_func=float)  # 获取所有元素--默认按照分数顺序排序
    33 print(conn.zscan("z1"))
    34 >>>(0, [(b'n1', 1.0), (b'v11', 1.0), (b'v2', 2.0)])
    35 
    36 5.1、zscan_iter(name, match=None, count=None,score_cast_func=float)  # 获取所有元素--迭代器(这个非常有用)
    37 print(conn.zscan_iter("z1"))
    38 for i in conn.zscan_iter("z1"):
    39     print(i)
    40 
    41 >>><generator object Redis.zscan_iter at 0x00000010F26047D8>
    42 (b'n1', 1.0)
    43 (b'v11', 1.0)
    44 (b'v2', 2.0)
    45 
    46 6、zrem(name, values)  # 删除--指定值删除
    47 
    48 7、zremrangebyrank(name, min, max)  # 删除--根据排行范围删除,按照索引号来删除
    49 
    50 8、zscore(name, value)  # 获取值对应的分数
    redis有序集合的操作
    4、一些相关的补充
     
     
  • 相关阅读:
    __PRETTY_FUNCTION__, __FUNCTION__, __func__
    Python.with
    golang配置
    论单位转个人的社保金融社保卡的作用
    面试题
    平衡是一门艺术
    画原型是节省人力的最好办法
    推荐给非互联网主体的用户
    iOS 点击返回键崩溃的未解之谜
    服务请求比较慢SYN flooding
  • 原文地址:https://www.cnblogs.com/pontoon/p/10307477.html
Copyright © 2020-2023  润新知