Redis之Datatype概述

官方原文档:

  https://redis.io/topics/data-types

  https://redis.io/topics/data-types-intro

Redis支持的数据类型:

String、List、Set、Sorted Set、Hashes、Bit array、HyperLogLog

Reids Keys(键):
  • Redis的键是二进制安全的:可以使用任何的二进制序列作为键。 比如"foo"这样的字符串,甚至是JPEG文件的二进制内容,空串""也是合法的键。
  • 不推荐使用特别长的键:
          影响性能,做键的比较,查找键是很耗费性能的
          同时对带宽以及内存要求很大,如果当前的任务是匹配大值的存在
          建议使用hash,比如SHA1 ,、MD5等
  • 不推荐使用特别短的键:
          例如使用"user:1000:followers"而不是"u1000flw"
          前者明显可读性高,而且增加的空间较小
  • 坚持用统一的命名结构:
          比如 "object-type:id"
          使用"."或"-"来表示由多个词语组成的字段
          比如"comment:1234:reply.to"或者"comment:1234:reply-to"
  • 键的最大长度是512MB
          这里的最大长度指的是单个key的长度
          对于value同样限制的是512MB

String类型(字符串类型)

  String 是Redis中最基本的类型。Redis中的String 类型是二进制安全的,也就是说在Redis中String类型可以包含各种数据,比如一张JPEG图片或者是一个序列化的Ruby对象。一个String类型的值最大长度可以是512M。

在Redis中String有很多有趣的用法,比如:

  • 把String当做原子计数器,这可以使用INCR家族中的命令来实现:INCRDECRINCRBY
  • 使用APPEND命令来给一个String追加内容。
  • 把String当做一个随机访问的向量(Vector),这可以使用GETRANGE和 SETRANGE命令来实现
  • 使用GETBIT 和SETBIT方法,在一个很小的空间中编码大量的数据,或者创建一个基于Redis的Bloom Filter 算法
List类型
    List有两种底层实现机制:一种是基于array,而另一种是基于linked list。
    而Redis中的list就是基于后者(linked list)
    这样做的好处就是:
           在list头部/尾部 添加数据的时候,都可以以很快的速度去处理,不管你是添加1条数据,还是插入1亿条数据效率上都是差不多的。
    坏处就是:
           当你访问list的时候,随着index的变大,消耗的时间也将成比例增加。
    如果访问一个比较大的list 中间的元素的需求比较重要的话,建议使用sorted set。
 
    常用命令:
           LPUSH,RPUSH,LPOP,RPOP,LRANGE,LTRIM ... 
           LRANGE 
                    接受3个参数:一个list实例参数,两个index参数(起始位置、结束位置)
                    两个index参数均可以为负数,表示list.size() - index 处的元素的索引数
                    LRANGE mylist 0 -3 
           LPUSH/RPUSH 
                    它们的参数是可变长的参数
                    具体来说第一个参数接收一个list实例,后面n个参数均是要添加到list最开始/最末端 的元素,多个参数之间用空格分割
                     LPUSH mylist 12 4 www "ss" 
           LTRIM 
                    类似于LRANGE,所不同的是 LRANGE只是为了展现,而LTRIM会将在它抽取的范围外的元素都给移除
                    和LPUSH合作,可以实现保留最新多少条数据
                    LPUSH mylist 100 3 4
                    LTRIM mylist 0 999 
          LPOP/RPOP
                    将list最前端/最尾端的元素返回回来,并且将它从源list中删除掉
                    可以和PUSH操作一起使用实现生产者消费者模式    
 
Redis的Lists类型有很多有趣的用法,比如:
  • 在社交网络中使用List进行时间表建模,使用LPUSH命令在用户时间线中加入新的元素,然后使用LRANGE 命令来获得最近加入的元素。
  • 可以把LPUSH 和LTRIM 命令结合使用来实现定长的列表,列表中只保存最近的N个元素
  • 在创建后台运行的工作时,Lists可以作为消息传递原语,例如著名的Ruby库 Resque
  • 还有很多可以使用lists来做的事,这种数据类型支持很多命令,包括像BLPOP这样的阻塞命令
    list最普遍的两个代表性用法
        1).记载用户发布到社交网络的最新更新
        2).使用消费者-生产者模式进行进程之间的通信:
                生产者向一个list中添加元素
                消费者消耗这些元素,并执行操作
                Redis提供了一些list命令来保证这种做法的高效性以及可靠性
    list拥有一个特性使得它适合实现 队列,并且通常作为进程间通信系统的构建块。这个特性就是BLPOPBRPOP 是个阻塞操作
 
    Note : 
            正常来讲 生产者消费者模式,当消费者向list索取元素的时候,发现该队列为空,那么消费者通常会进行等待一会儿,然后再重试索取(这个过程叫轮询)
            这样,会导致redis以及客户端都做了很多无用的命令行操作,因此Redis提供了两个阻塞型的 pop 操作
            当list为空时,只有当新的元素被添加到list中后或者达到了用户指定的超时时间,BRPOP/BLPOP指令才会返回给调用者(一个结果)
    
            demo : 
                    BRPOP tasks 5  --等待tasks中的元素,如果超过5秒钟没有可以用的元素,就返回
   
            如果timeout参数 设置为 0 ,那么会永远等待新元素(不会超时,一直阻塞)
            其中list参数可以接受 多个列表,比如task1 task2 ...,当有一个列表任务有新增元素,就返回pop的结果
    
    关于BRPOP/BLPOP的一些需要注意的事情:
          1).客户端是按照顺序来享受服务的
                   第一个客户端阻塞的来等待一个list,那么当有新的元素被其它的客户端push进来,那么它(即第一个客户端)将会首先享受这个服务 
          2).和RPOP/LPOP的返回值不同
                  它是个包含键名的双元素的数组,因为BRPOP/BLPOP可以同时阻塞式地从多个list列表中等待元素 
          3).如果过期时间的阀值到了,将返回NULL
 
    关于list以及阻塞操作的更多内容:
         1).可以使用RPOPLPUSH指令 来构建更安全的队列 或者 旋转队列
         2).redis提供了一个阻塞的变种指令:BRPOPLPUSH
 
    主键的自动创建与删除
            三条规则来总结:
                1). 当我们添加一个元素到聚合数据类型,如果目标关键字不存在,在添加这个元素之前会(自动)创建一个空的聚合数据类型
                2). 当我们从聚合数据类型中移除元素的时候,,如果该值是空的,那么键也将自动被销毁
                3). 调用 只读命令/移除元素的写命令 在一个空的关键字上,永远会返回同样的结果,好像该关键字正持有命令行希望找到空的数据类型
 
Hashes (散列.哈希类型)
    Redis Hashes 保存 string fields和 string values之间的映射,所以它们是用来表示对象的绝佳数据类型(比如一个User对象):
    > hmset user:1000 username antirez birthyear 1977 verified 1
  OK
  > hget user:1000 username
  "antirez"
  > hget user:1000 birthyear
  "1977"
  > hgetall user:1000
  1) "username"
  2) "antirez"
  3) "birthyear"
  4) "1977"
  5) "verified"
  6) "1"

    一个有着少量数据域(这里的少量大概100上下)的hash,其存储方式占用很小的空间,所以在一个小的Redis实例中就可以存储上百万的这种对象。

    虽然Hashes主要用于表示对象,他们可以存储很多的元素,所以你可以使用Hashes来做许多其他的工作。

    Hash的最大长度是2^32 – 1个域值对(4294967295,一个Hash中可以有多达40多亿个域值对)

Sets类型(集合类型)
    Redis的Sets类型是String的无序集合。增加,删除,测试元素是否存在的时间复杂度都是O(1)(不管集合中有多少元素都是稳定的时间消耗)
    Redis Sets的一个重要特性是不允许重复元素。向集合中添加多次相同的元素,集合中只存在一个该元素。在实际应用中,这意味着在添加一个元素前不需要先检查元素是否存在。
    关于Redis Sets一个非常有意思的事情是,它们支持多个服务器端命令来从现有集合开始计算集合,所以执行集合的交集,并集,差集都可以很快。
    set的最大长度是2^32 – 1个元素(4294967295,一个set中可以有多达40多亿个元素)

Redis Sets有很多有趣的用法,比如:

  • 你可以使用Redis Sets来记录唯一的事物,比如,你想知道访问某个博客的IP地址,不要重复的IP,这种情况只需要在每次处理一个请求时简单的使用SADD命令就可以了,可以确信不会插入重复的IP.
  • Redis Sets 可以很好的表示关系。你可以使用Redis创建一个标签系统,每个标签使用一个Set来表示。然后你可以使用SADD 命令把具有特定标签的所有对象的所有ID放在表示这个标签的Set中。如果你想要知道同时拥有三个不同标签的对象,那么使用SINTER命令就好了。
  • 你可以使用SPOP 或者 SRANDMEMBER 命令从集合中随机的提取元素。
Sorted sets 类型(有序集合类型)
    Redis有序集合类型与Redis的集合类型类似,是非重复的String元素的集合,Sorted Set像是Set以及Hash的混合体。不同之处在于,有序集合中的每个成员都关联一个Score,Score是在排序时候使用的,按照Score的值从小到大进行排序。集合中每个元素是唯一的,但Score有可能重复。
    使用有序集合可以很高效的进行,添加,移除,更新元素的操作(时间消耗与元素个数的对数成比例)。由于元素在集合中的位置是有序的,使用get ranges by score或者by rank(位置)来顺序获取或者随机读取效率都很高。(本句不确定,未完全理解原文意思,是根据自己对Redis的浅显理解进行的翻译)访问有序集合中间部分的元素也非常快,所以可以把有序集合当做一个不允许重复元素的智能列表,你可以快速访问需要的一切:获取有序元素,快速存在测试,快速访问中间的元素等等。
    简短来说,使用有序集合可以实现很多高性能的工作,这一点在其他数据库是很难实现的。

使用有序集合你可以:

  • 在大型在线游戏中创建一个排行榜,每次有新的成绩提交,使用ZADD命令加入到有序集合中。可以使用ZRANGE命令轻松获得成绩名列前茅的玩家,你也可以使用ZRANK根据一个用户名获得该用户的分数排名。把ZRANK 和 ZRANGE结合使用你可以获得与某个指定用户分数接近的其他用户。这些操作都很高效。
  • 有序集合经常被用来索引存储在Redis中的数据。比如,如果你有很多用户,用Hash来表示,可以使用有序集合来为这些用户创建索引,使用年龄作为Score,使用用户的ID作为Value,这样的话使用ZRANGEBYSCORE 命令可以轻松和快速的获得某一年龄段的用户。
    排序规则:
          1).按照score(一个设置的浮点值)从小到大顺序排列的
          2).如果score一致,那么按照value的字段顺序排列
    实践注意:
          Sorted Set实现自两个接口(dual-ported):skip list 以及 hash table
          因此每次添加元素的时候,以O(log(N))复杂度进行操作.,这个复杂度是ok的
          但取数的时候,redis几乎不用做什么额外操作,因为顺序是已经排列好的
    常用命令:
           ZADD     some_set     any_score     the_element
           ZRANGE     some_set     start_index     end_index     [withscores]
           ZREVRANGE     some_set     start_index     end_index     [withsores]
           ZRANGEBYSCORE     some_set     -inf     any_score
           ZREMRANGEBYSCORE     some_set     any_start_score     any_end_score
           ZREVRANK     some_set
 
以下命令是基于字典而非score来取得结果的
            ZRANGEBYLEX , ZREVRANGEBYLEX , ZREMRANGEBYLEX , ZLEXCOUNT
        
            demo : zrangebylex hackers [B [P -- 表示闭区间
 
            注意,所有*range*的操作,都会把这些元素从set中删除哦
 
Bitmap
    Bitmap 并非是一种数据类型,而是String类型上的一组"面向-位"的操作 
    由于String是二进制安全的大文本(可以有512M大小),因此就有了 2^32种不同的位组合 
    bit操作分为两组:常量时间-单个位 的操作;bit组的操作(即多个bit的批量操作)
 
    常用命令 SETBIT , GETBIT , BITOP , BITCOUNT , BITPOS
 
    bitmap普遍使用场景:
        1).各种实时分析
        2).存储和对象id关联的boolean信息,,高效而又节省空间
 
HyperLogLog (以下简称HLL)
    redis提供的一种概率数据结构,用于计算唯一事物(技术上来讲,是指估计一个集合的基数)
    如果用其它方式,会消耗成比例的内存来实现
    而是用redis提供的hyperloglog,可以得到比较精确的统计结果,这个结果相比真实结果,误差小于1%
    
    使用 PFADD 来添加计数;使用 PFCOUNT 来查询集合中的基数
 
    HLL中不会真的存储这些元素,该数据结构只保存一个状态
 
Redis的其它显著特性
    1).支持 对大集合的中的键空间进行逐步迭代
    2).可以云信Lua脚本服务器端 来提升延迟和带宽
    3).Redis也是一个pub-sub服务器(即发布与订阅)
原文地址:https://www.cnblogs.com/hypo106/p/13258190.html