运行32位仍是64位位版本的redis将决定redis键大小的实际限制。对于32位版原本说,任何长于32位的键名须要更多的字节空间,所以增长了redis的内存使用。使用64位版本的redis容许更长的键长度,可是对于短小的键来讲,也会分配完整的64位空间,从而致使额外的空间浪费。前端
虽然redis官方教程data types推荐在命名键时使用一致的模式,可是redis自己并无模式检测或者验证的功能。不过能够经过使用EXISTS和TYPE这些redis命令实现一些基本的验证。若是应用须要明确特定类型的redis键是否存在于实例中,能够经过使用EXISTS命令,随后使用TYPE命令确认该键是不是指望的redis数据结构。除了这俩命令之外,验证redis键语法和结构须要客户端代码来实现。node
若是redis应用会在不一样的系统和组织中共享,那么为应用程序添加额外的验证逻辑层将十分有用。一份精确详尽的redis键模式能极大地在排查故障和调试问题方面带来帮助。另外一种验证redis键模式的方法是为redis应用引入具体的单元测试。用来测试边界条件、模式键语法和结构,还有每一个验证过的键所指望的数据结构。第三种验证redis键模式的方式是使用DTD或者其余基于XML的键结构验证,或者使用新的键验证技术,例如 JSOB Schema.web
一份精心设计的键模式应当为现存的(基于redis的)应用程序在添加新的键时提供指引。若是模式描述得足够清楚而且可以保持一致性的话,那么新的redis键的命名就不该当有任何神秘色彩。能够利用名词的单复数形式鉴别存储到redis的实体内容与个数。redis
例如,book:1做为redis哈希类型存储了单一书本的相关字段,而redis键books:sci-fiction则存储了一套科幻类小说。有序集合能够用做图书销售排行,将books:scale-rank做为键名称,图书销售做为权重(有序集合的分值),并将图书键做为值。算法
对于一个简单的图书应用来讲,基于文本的redis模式实例以下:sql
即使是简单的、一次性的redis项目,将键模式文档添加到项目的源代码仓库也是一种很好的实践。数据库
在上例中,咱们使用“:”做为键的分隔符。对于符合redis键来讲,推荐使用冒号做为分隔符。编程
另外一种redis键分隔符是英文字符句号“.”。大多数流行的编程语言,都青睐这种面向对象的语法。json
高效的redis键模式体如今创建命名约定以便将相关的键关联起来。应用程序和业务逻辑经过客户端代码应用在这些松散耦合的redis键上。以以前的图书键模式为例,扩展一下需求,让redis数据库包含其余媒体类型,在redis命令行工具中运行keys命令,并作一些格式化工做。咱们能够从redis键模式中观察到一种模式和隐含的关系:缓存
在此redis应用程序中,图书和影片都提供了基本的前缀。那些用于支持的数据结构,经过基本前缀关联到单本图书或者单部影片,或者关联到包含额外实体哈希的集合上。
每件做品都是有redis键做为前缀,同时加上一个全局计数的哈希。在此示例中,其余用于支持的数据结构,即图书和影片的系列与格式,都是redis集合,其中存储了全部图书或者影片的键,并以特别的系列或者格式进行分类。举例来讲,Isaac Asimov 的 Foundation 属性将存储在 book:2 哈希表中。同时,book:2 又是 books:genre:sci-fiction 和 books:format:paperback 集合的成员,也是 books:sales-rank 和 all:sales-rank 有序集合中的一项。一样地,Orson Well的 Citizen Kane 存储在 film:1 哈希表中,同时也是 films:genre:drama 和 films:format:dvd 集合的成员,而且也是films:sale-rank 和all:sales-rank有序集合中的一项。
一般应用程序须要依据共同的特征获取集合的值。在图书示例中,咱们尝试使用KEYS命令和 books:genre:* 模式获取全部的图书体裁。强烈建议 不要在生产环境的应用中使用redis的keys命令,这是由于redis须要遍历数据库中的每一个键。采用一致的命名约定及诸如集合、哈希或者有序集合这样的数据结构,应用程序理应无须使用keys命令获取数据。虽然scan命令能够用来获取redis数据,但不该被视为keys命令的替代品。scan命令抽取一个随机的键片断,而后将提供的模式和match选项应用到此随机片断上。回顾以前的示例,下述redis-cli 程序中运行的scan命令的用法仅对小型数据库有效:
若是数据库再大一点,那么scan命令可能会没法匹配任何数据或者只返回全部匹配数据的一个子集。所以,将全部的键存储在books:genre集合中才是明智之举,这样应用程序就能够像使用索引同样,使用smembers命令快速获取全部图书体裁的键:
测试键之间的关系及它们是如何经过redis键命名约定来相互关联的,这取决于众多因素,其中包括应用程序是否直接与redis示例交互。添加单元测试来明确地检测redis应用的键分割符及命名约定,能够确保redis数据库中存储的数据精确地表达了应用程序所依赖的假设和需求。
-----------------------------------------------------------------------------------------------------------------
第一步是创建全局信纸计数器,并附加在用于出售的信纸类型和品牌的信纸前缀以后。将颜色和尺寸属性存储为stationery:{id-counter}哈希中的字段,并将信纸张数存储到另外一个stationery:{id-counter}:sheets 键所对应的字符串上。
10.143.128.165:6379> incr global:stationery 1
返回的整数1将用做第一个信纸的id:
10.143.128.165:6379> hmset stationery:1 color blue width '30 cm' height '40 cm' OK
为了将纸张和stationery:1:sheets 集合关联起来,使用increby命令:
10.143.128.165:6379> incrby stationery:1:sheets 20 20
如今,咱们再次调用incr命令为第二种信纸类型生成id,填充哈希增长15张信纸:
10.143.128.165:6379> incr global:stationery 2 10.143.128.165:6379> hmset stationery:2 color red width '45 cm' height '45 cm' OK 10.143.128.165:6379> incrby stationery:2:sheets 15 15
接下来,特定类型的信纸包裹库存存储在stationery:<stationery id>:inventory 键模式中,键对应的值是简单的整数,用来表示那种类型的信纸的可用包裹总数。
初始库存 250件包裹:
10.143.128.165:6379> set stationery:1:inventory 250 OK
当包裹销售出去后,stationery:1:inventory 键对应的整数将减去销售的包裹数量;经销商送来新的信纸包裹时,键被加上新的信纸包裹总数。
10.143.128.165:6379> decr stationery:1:inventory 249 10.143.128.165:6379> incrby stationery:1:inventory 10 259
每件包裹的销售数据存储在一个有序集合中。集合中每行以unix时间戳做为分值,并以销售数量做为值。将stationery:1:sales做为有序集合的redis键,记录一笔20美圆的销售:
10.143.128.165:6379> zadd stationery:1:sales 1430861194 20.00 1
对node.js来讲,redis对象映射器成为Nohm,经过使用JavaScript对象模型建立redis模式。使用Nohm为信纸实体建模,首先须要定义信纸的JavaScript模型的颜色、高度、宽度属性:
会产生下列redis命令:
Nohm在基础命名模式中使用冒号做为键分隔符。
1.paper:meta:version:Stationary 该redis元数据键存储信纸的字符串版本。该键的值被设置为一个随机元数据版本字符串1bf8ca.....8d65c
2.paper:idsets:Stationary 该redis集合存储了全部信纸id。该集合首先被一个负的Unix时间戳检测,而后产生了一个值为i9hiar...9rgc5的id字符串,并被添加到该集合中。该集合是用来追踪信纸对象的,随机值能够最小化重复键的问题。
3.paper:meta:idGenerator:Stationary Nohm使用该redis字符串决定生成id的方法。默认的选项产生随机字符串。递增选项则使用整数计数器。
4.paper:meta:properties:Stationary 该redis字符串存储了信纸对象的序列化json元数据。
5.paper:hash:Stationary:i9hira0.....9rgc5 信纸JavaScript对象把i9hira0.....9rgc5 做为redis键的末尾部分,将其属性值存储在redis哈希中。这些操做封装在一个事务中。
再添加第二个信纸包裹,即红色方形,45 cm高 * 45 cm 宽,初始纸张数为15.于是在数据库中会有如下redis键:
使用Nohm为信纸项目的销售建模时,要使用来自 schema.org 元数据词汇表的两个支持类,一个名为offer类,另外一个名为order类。schema.org 用来表示web上的结构化数据。offer类包含了价格和可用库用,以及用于支持其余货币的priceCurency属性,默认货币单位美圆。order类包含了acceptedOffer和orderDate属性,acceptedOffer属性链接到咱们为信纸建立具体订单。
order类包含两个属性,分别命名为orderDate和orderedItem。
当交易发生时,Nohm会在offer、order、stationery这三者之间建立关联。在使用交易发生时间建立新的订单实例以后,Nohm使用几个redis集合为这三个不一样的类之间的关系进行建模。
首先、红色信纸的哈希键为paper:hash:Offer:ia4ev....968h,并将库存级别属性设置为50,价格为15.
下一步是建立paper:relationKeys:Offer:ia4ev8....6p968h 和 paper:relations:Offer:itemOffered:Stationery:ia4ev8...968h 集合。第一个集合中存储的键对应的集合中,存储了那些经过itemOffered属性建立offer和stationery之间的关联。第二个集合经过建立具体的offer和stationery之间的具体关联,存储了全部单独的信纸ID。
当接受订单而且交易被确认时,redis paper:hash:Order:1 哈希使用订单日期属性被建立出来,同时 经过Nohm,元数据版本id使用哈希值做为属性被存储。
两个额外的集合,分别命名为paper:relationKeys:Order:1和paper:relations:Order:offer:Offer:1,建立了order和offer之间的关联。第一个集合为order存储了全部的关联链接。第二个集合为以前命令添加的order存储了特定的offer。
redis可以为键设置过时时间。经过自动化删除过时键,redis应用程序可以很好的管理数据库所使用的内存大小和使用状况,同时减小用于追踪数据库中每一个键的客户端代码量。能够对redis配置文件的选项进行设置,也能够在运行时向redis数据库发送命令进行设置。
redis键的大小应该受到限制,不只由于键的大小超过1024字节会致使内存增加,大尺寸的键还会令redis实例的开发者和用户感到困惑。随着redis实例大小的增加,这些过长的键名称开始消耗更多的内存,从而挤压了正常数据所需的内存空间。
一样的,若是键名称过短,额外节省的内存可能得不偿失。由于对redis进行故障排除或者经过新的redis键添加新的功能时,会遇到各类问题。
redis的keys命令应当在万不得已时使用,由于它对redis实例形成长时间的阻塞,甚至会致使redis内存耗尽。
scan命令为redis中全部的键提供了一个迭代器,能够对全部的键进行增量式调用。若是一个元素在从头至尾的迭代中不是始终存在的,那么scan命令并不保证该元素可以返回。
数学上对大O符号的定义为“象征性的表达给定函数的渐进行为”。在计算机科学和对redis中大O符号的理解的帮助下,可以经过这些命令在面对不断增加的输入时的性能表现,对redis命令作出性能上的区分。
1. O(1) 随着输入的增长而不会对时间或者处理形成变化。性能的上线是线性时间,随着输入增长不会致使性能的降低,但受算法自己复杂性的限制。
2. O(log n) 对数时间,它对每一个输入进行操做,返回的结果大于O(1),可是性能等价于对n求对数。
3.O(n) 遵循尝试观念,即添加额外的单元以恒定比例的量增长处理时间。
4. O(n log n) 对数线性时间, O(log n) 做用于每个输入之上。实际上,在O(n log n)算法中每次输入都增长了一倍以上。
5. O(n^2) 即平方时间来讲,随着n的增加,时间的量也成倍增加。对于每一个加倍的n来讲,时间处理变为原来的4倍。O(n^2) 算法的性能在n较小的状况下也许是能够接受的,可是当n增加到必定量时,就很快变得不切实际。
6.O(2^n) 指数时间,对于每个额外的输入,时间都会加倍。
7. O(n!) 阶乘时间,输入的n轻微的增长都会致使处理时间太高。
根据redis文档中为每一个命令提供的大O符号,能够为任何提议的基于redis的解决方案计算出一个粗略的效率估计。一个简单的方案就是对于必定级别的n将全部redis命令的大O符号相加,而后为实现代码估计大O符号,以便为整个解决方案作粗略的时间效率估计。举例来讲,用redis实现的缓存只是简单的set和get调用,该解决方案的大O符号就是O(1)+O(1)=2个时间单位。
对数据结构的时间复杂度的评估不只包括数据结构自己,还包括对数据进行采集与提取等redis命令总数的优化。
redis值中最基本的数据结构为字符串,也就是和redis键相同的数据类型。
redis有着和其余诸如memecached之类键值数据存储解决方案类似的性能特色。
在redis中,字符串并不只仅是那些高级编程语言中包括字母数字字符的字符串,而是包含C语言(redis主要采用的编程语言)的序列化字符。redis字符串中最基础的get和set命令都是O(1)操做。这使得redis做为简单的键值存储及其快速。在思考redis解决方案时,get和set命令使用起来的快速和简单不容忽视。
对于大多数redis字符串操做来讲,访问和采集命令的时间复杂度要么是O(1),要么是O(n)。其中O(n)字符串命令大可能是块命令,GETRANGE 、MSET、MGET。GETRANGE 命令是一种O(n)操做,其中n为返回字符串的长度。若是将该操做比做一系列小的get命令(虽然get不返回存储在键中的字符串的子串),则理解起来更直观。
10.143.128.165:6379> set organization:1 "The British Library" OK 10.143.128.165:6379> GETRANGE organization:1 4 10 British
在该示例中,对于set命令来讲 大O符号 +1 ,同时对于getrange 来讲 大O符号+6,等价于发送独立的伪get命令获取6个字符。
因为redis将全部数据做为字符串存储,特定字符串的类型信息也会被维护起来以支持 INCR/DECR 和BITSTRING 命令。对于 INCR/DECR 命令来讲,存储的值是以10为基数的64位有符号整数字符串命令。若是该值被其余诸如APPEND的redis字符串命令修改过,可能会致使破坏。于是以后做用在同一键上的与整数相关的redis命令都会失败。
10.143.128.165:6379> incr new:counter 1 10.143.128.165:6379> get new:counter 1 10.143.128.165:6379> dump new:counter "\x00\xc0\x01\x06\x00\xb0\x95\x8f6$T-o" 10.143.128.165:6379> append new:counter "a" (integer) 2 10.143.128.165:6379> get new:counter "1a" 10.143.128.165:6379> incr new:counter (error) ERR value is not an integer or out of range 10.143.128.165:6379> dump new:counter "\x00\x021a\x06\x00\x8br\x9a\x98-9\x9a\xa6"
将一个或多个字段映射到对应的值的数据结构。
在redis中,全部的哈希值必须是redis字符串,而且有惟一的字段名。字段的值是简单的redis字符串。
经过调用redis的 HGET 或者 HMGET 命令,同时传入合适的redis键和一到多个字段参数,就能返回字段的值。
对于大多数使用场景,redis哈希为HSET和HGET命令提供了很棒的 O(1) 性能。与字符串块命令相似,哈希的HGETALL、HMSET、HMGET、HKEYS、HVALS命令均为 O(n)。若是哈希很是小,那么返回全部哈希键和值的HGETALL和HMGET命令以前没有十分明显的差别。当哈希中键和值不断增加时,二者之间的差别可让应用程序大不相同。假设哈希中有1000个字段,若是应用程序只是常用其中的300个,对redis调用HGETALL和HVALS的时间复杂度为O(1000),而使用HMGET的时间复杂度只有O(300)。这是由于虽然HGETALL和HMGET都是 O(n),可是对于 HMGET 其上限为所请求字段的总和而非整个哈希。哈希的整体较小时,将HMGET替换为HGETALL是增长redis性能的一种方式。对于大型哈希来讲,返回大量值的 HMGET 命令在完成执行前会阻塞其余客户端接受数据,从而极大的影响redis的整体性能。在这种状况下,有针对性的 HGET 会是更好的选择。
redis哈希的值不能包括哈希、列表 及 其余数据集合结构,可是redis提供了 HINCRBY 和 HINCRBYFLOAT命令,容许将字段中存储的字符串值当作整数或者浮点数操做。若是你尝试更新字段的值 可是弄错了数据类型,redis会返回错误:
10.143.128.165:6379> HMSET weather:2 temperature 46 moisture .001 OK 10.143.128.165:6379> HINCRBY weather:2 temperature -1 (integer) 45 10.143.128.165:6379> HGET weather:2 temperature "45" 10.143.128.165:6379> HINCRBY weather:2 moisture 1 (error) ERR hash value is not an integer 10.143.128.165:6379> HINCRBYFLOAT weather:2 moisture 1 "1.001" 10.143.128.165:6379> HGET weather:2 moisture "1.001"
redis会根据命令来区分设置的值1是整数仍是浮点数。
在redis中列表是字符串的有序集合,它容许重复的字符串值。redis中的列表被更准确地标记和实现为链表。因为redis列表以链表的方式实现的,使用 LPUSH 向列表前端或者 RPUSH 向列表末尾添加条目是相对廉价的操做,表现为常数时间复杂度 O(1) .对于 LINSERT 和 LSET 命令来讲,时间复杂度是线性的 O(n),但二者有些重要的差异。 LSET 能够指定下标值来设置列表的值。因为本质上是链表,所以变量n是列表的长度,同时无论是设置列表中的第一项仍是最后一项,时间复杂度均为 O(1)。LINSERT 能够在参考值以前或者以后插入值,上述操做的时间复杂度为 O(n)。其中n为列表元素的个数。该命令必须一致查找直到获取到参考值,最坏的状况是将值插入列表的末尾,所以 LINSERT 时间复杂度O(n),即使是特殊状况下参考值是列表当中第一个元素,使得 LINSERT 命令复杂度为O(1)。
LRANGE 时间复杂度 O(s+n),s为从列表的表头(或表尾)到偏移量位置的元素个数,这取决于列表的大小。n 表明返回的元素总数。若是想要返回整个列表(长度=10),该操做的时间复杂度 O(10+10)。
LTRIM时间复杂度O(n),n为返回给客户端的元素数量。
使用 LTRIM 结合 RPUSH 或者 LPUSH,是存储固定长度的集合的经常使用方法。
示例,只想保存最近7天有价值的平均温度数据:
10.143.128.165:6379> LPUSH temp:last-seven-days 30 45 50 52 49 55 51 (integer) 7 10.143.128.165:6379> LPUSH temp:last-seven-days 56 (integer) 8 10.143.128.165:6379> LTRIM temp:last-seven-days 0 6 OK 10.143.128.165:6379> LRANGE temp:last-seven-days 0 -1 1) "56" 2) "51" 3) "55" 4) "49" 5) "52" 6) "50" 7) "45"
这种模式容许咱们存储最近7天的平均温度,而且当采用这种方法时,因为每次只有一个值添加到列表中,LTRIM 时间复杂度接近O(1)。
redis中的集合保证了字符串值的惟一性,可是不保证这些值的顺序。redis集合实现了集合语义的并集、交集、差集,并在redis实例中将这些集合操做的结果存储为一个新的redis集合。以当前的redis集群的实现来讲,并集、交集、差集 这些集合语义受到了诸多限制,而且只能以受限的方式使用。
SADD 将一到多个值添加到集合中,时间复杂度O(n),n为须要添加到集合的元素总数。
SISMEMBER 用于判断值是否为集合的成员,时间复杂度O(1)。
SMEMBERS 返回集合中全部成员的列表,时间复杂度O(n)。
集合可能有着与redis中其余数据结构类似的性能。在某些状况下,相较于哈希,集合拥有更佳的内存使用率。
redis中集合特别有用的地方在于对集合 并集、交集、差集操做的支持,全部这些操做有着不一样的时间复杂度,在redis集群中使用会受到限制。
SUNION 和 SUNIONSTORE 容许将多个集合的全部成员返回给客户端或者存储为redis中的新集合,时间复杂度O(n),n为全部集合中元素的总数。
SINTER 和 SINTERSTORE 命令返回集合的交集,后者会将返回的集合存储在redis中,时间复杂度O(n*m),n是最小集合的大小,m为集合的总数。
SDIFF 和 SDIFFSTORE 返回或者存储第一个集合和后续集合之间的差别,时间复杂度O(n),n为全部集合中元素的总数。
redis中,有序集合数据类型兼备redis列表和集合的特性。集合中的值是有序的,每一个值都是惟一的。
在游戏中使用单一有序集合能够记录玩家得分,ZRANGE或者ZREVRANGE,从排行榜中获取排名靠前和靠后的玩家。
ZADD 将成员和分值一块儿添加到有序集合中,时间复杂度 O(log(n)),随着有序集合的大小的增长,处理时间的增长比率是一个常量。
若是有序集合中全部或部分元素的分值相同,这些值以字典字母顺序进行排序,用于文本字符串的字母排序。
将7种颜色添加到一个为colors的有序集合中:
10.143.128.165:6379> ZADD colors 0 red 0 blue 0 green 0 orange 0 yellow 0 purple 0 pink (integer) 7
如今,经过ZRANGE命令命令将颜色以字母顺序取出:
10.143.128.165:6379> ZRANGE colors 0 -1 1) "blue" 2) "green" 3) "orange" 4) "pink" 5) "purple" 6) "red" 7) "yellow"
能够以ZREVRANGE 以字母倒叙的形式获取数据:
10.143.128.165:6379> ZREVRANGE colors 0 -1 1) "yellow" 2) "red" 3) "purple" 4) "pink" 5) "orange" 6) "green" 7) "blue"
无论哪一个示例,在colors有序集合中,全部的分值都是相同的。
可使用 ZREVRANGE 命令上带上 WITHSCORES 关键字:
10.143.128.165:6379> ZREVRANGE colors 0 -1 WITHSCORES 1) "yellow" 2) "0" 3) "red" 4) "0" 5) "purple" 6) "0" 7) "pink" 8) "0" 9) "orange" 10) "0" 11) "green" 12) "0" 13) "blue" 14) "0"
LRANGEBYLEX 和 LREVRANGEBYLEX 以字典顺序获取元素,经过特定的语法指定有序集合额起止位置。
10.143.128.165:6379> ZADD myzset 0 a 0 b 0 c 0 d 0 e 0 f 0 g (integer) 7 10.143.128.165:6379> ZRANGEBYLEX myzset - [c 1) "a" 2) "b" 3) "c" 10.143.128.165:6379> ZRANGEBYLEX myzset - (c 1) "a" 2) "b" 10.143.128.165:6379> ZRANGEBYLEX myzset [a (g 1) "a" 2) "b" 3) "c" 4) "d" 5) "e" 6) "f"
当redis使用集群时,并集和交集的操做只能在有序集合键被分片分片到同一哈希槽中,且运行在同一个节点上。
ZINTERSTORE 时间复杂度 O(nk)+O(mlog(m)),n为最小有序集合的大小,k为这些求交集的有序集合的总数,m为最后返回的有序集合计算结果中元素的个数。
ZUNIONSTORE 时间复杂度 O(n)+O(M log(M)),n表明全部有序集合的大小总数,m表明最终有序集合的元素总数。
大型集合和有序集合之间的性能差别 与 是否须要排序无关。
---------------------------------------------------------------------------
redis字符串和对应命令的特殊用法 容许为redis中相对较少数量的比特使用内存高效的数据结构。
同时,取决于具体的用例场景和数据,使用集合和哈希会提供更好的性能。
在位串中,每一个字节存储8位,其中位置0处为最高有效位,它被设置为0或者1。
redis的位串最大为512MB,这和redis全部的键和值的限制是一致的。
位串如此高效快速的一个缘由是大多数针对它的时间复杂度为O(1)或O(n)。
使用SETBIT和GETBIT 命令,能够将位设置为0或者1,或者获取值,时间复杂度均为 O(1) 。
位串对于存储一系列连续值的二进制信息来讲 及其迅速。
BITOP、BITPOS、BITCOUNT,时间复杂度 O(n) ,对位串的使用提供了强大的语义。
位串经常使用的用例场景是 存储用于表示 一系列顺序的键的布尔值,即0或者1。
举例,若是想在网站上追踪每日的使用状况,能够从简单的“customer:”模式开始,用来为每位客户存储用户名、哈希过的密码和电子邮件地址:
10.143.128.165:6379> INCR global:customer (integer) 2445 10.143.128.165:6379> HMSET global:customer:2445 username mmaxwell password '49dffdfsdfdfd' email mmaxwell@gmail.com OK
假设顾客计数从0开始,顾客mmaxwell是连续第2445位顾客。如今,为了记录mmaxwell在2016-02-11 访问了咱们的网站,咱们会设置 2016/02/11:usage 位串的第2445位位,以下:
10.143.128.165:6379> SETBIT 2016/02/11:usage 2445 1
若是咱们想查看mmaxwell是否在那天访问了咱们的网站,能够经过GETBIT命令获取存储在2445上位的值:
10.143.128.165:6379> GETBIT 2016/02/11:usage 2445 (integer) 1
查找2月11号当天的网站顾客访问统计能够简单地经过 BITCOUNT 命令达成:
10.143.128.165:6379> BITCOUNT 2016/02/11:usage (integer) 365
在2月的这一天,咱们共有365位客户访问。
假设咱们正在跟踪每周顾客的使用状况,可使用 BITOP 命令和 OR 操做,根据多个位串生成使用状况,统计的结果存储在新的键中:
10.143.128.165:6379> BITOP OR 2016/02/week2:usage 2016/02/07:usage 2016/02/08:usage 2016/02/09:usage 2016/02/10:usage 2016/02/11:usage 2016/02/12:usage 2016/02/13:usage (integer) 306 10.143.128.165:6379> BITCOUNT 2016/02/week2:usage (integer) 4
为了计算月度总计并将结果存储在新的键 2016/02:usage 中,能够再次执行 BITOP 命令:
10.143.128.165:6379> BITOP OR 2016/02:usage 2016/02/week2:usage 2016/02/week3:usage (integer) 306 10.143.128.165:6379> BITCOUNT 2016/02:usage (integer) 7
最后,整个网站的年度总计 能够针对12个月的位串再次调用BITOP OR操做:
10.143.128.165:6379> BITOP OR 2016:usage 2016/02:usage (integer) 306 10.143.128.165:6379> BITCOUNT 2016:usage (integer) 7
最新的redis数据类型是一个几率数据结构,用来对集合中的惟一项作估计总数。
使用 PFADD 将一到多个元素添加到 HyperLogLogs 中的时间复杂度为O(1) ,
经过PFCOUNT 获取单个HyperLogLogs中惟一元素的总计,时间复杂度也是O(1)。
PFCOUNT 计算多个 HyperLogLogs 中元素惟一的总计,性能为O(n),n表明键的总数。
待续 P61