redis基础知识

redis基础知识

     Redis有9种基本数据类型,大部分盆友最熟悉的有这5种:string、hash、list、set、zset。其实,除此之外,经常用到的还有:bitmap、hyperloglog、geohash、stream

     下面来整理下各个数据类型的概念和基本用法。

一、 普通数据类型(5种)

     Redis支持5种最基本的数据类型:string(字符串),hash(哈希),list(列表),set(集合)及 zset (sorted set:有序集合)。

     1、String

     1)String是简单的 key-value 键值对,value 可以是字符串,也可以是数字

     相关命令:

     SET key value

     GET key

     MSET

     MGET

     INCR

     INCRBY

     DECR

     DECRBY

     DEL

     EXPIRE

     TTL

      

    补充:为什么incr/decr具有原子性

    答:Redis的操作之所以是原子性的,是因为Redis是单线程的线程,是操作系统最小的执行单元,在单线程程序中,任务是要一个一个地做,必须做完一个任务后才会去做另一个任务

    2、List(列表)

    Redis列表是简单的字符串列表

    相关命令:

    LPUSH key value1 [value2]

    LPUSHX key value  将一个值插入到已存在的列表头部,列表不存在时操作无效

    LLEN

    LRANGE

    LPOP key

    LREM key count value

    LTRIM key start stop

    RPOP

    RPUSH

    RPUSHX

    BLPOP

    BRPOP

    BRPOPLPUSH LIST1 ANOTHER_LIST TIMEOUT 

    说明: BRPOPLPUSH: 从列表中取出最后一个元素,并插入到另外一个列表的头部; 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。这个过程具有原子性。

    

    3、Hash(字典)

    相关命令:

    HSET

    HMSET

    HLEN

    HKEYS

    HGET

    HINCRBY

    HGETALL

    HSCAN

    

    4、Set(集合)

    Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。

    相关命令:

    SADD

    SMEMBERS

    SCARD

    SRANDMEMBER  KEY [count]

    SINTER

    SISMEMBER

    SREM

    

    5、Sorted Set(有序集合)

    Redis有序集合类似Redis集合,不同的是增加了一个功能,即集合是有序的。一个有序集合的每个成员带有分数,用于进行排序。有序集合的成员是唯一的,但分数(score)却可以重复。

    相关命令:

    ZADD key score1 member1 [score2 member2]   注意:score 值可以是整数值或双精度浮点数

    ZCARD

    ZCOUNT key min max

    ZINCRBY

    ZRANGE

    ZRANGEBYSCORE

    ZREVRANGE

    ZRANK

    

    关于zrank的使用,需要注意:

    1)  返回有序集中指定成员的排名(索引下表)。

    2)  其中有序集成员按分数值递增(从小到大)顺序排列

    3)  如果需要依据分值从高到低来排列,需要使用zrevrank

     

    二、高级数据结构(3种)

     Redis中3种高级数据结构分别是HyperLogLog、bitmap、GEO

     1、HyperLogLog

     Redis 在 2.8.9 版本添加了 HyperLogLog 结构,它是用来做基数统计的算法。

     相关命令:
     PFADD key element [element...]
     PFCOUNT
     PFMERGE

     

    说明:

    1)HyperLogLog的计数统计是有一定的误差的,误差最大在1%以下

    2)Redis中每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。

    3)因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素

    4)什么是基数?

    比如数据集 {1, 3, 5, 7, 5, 7, 8}, 那么这个数据集的基数集为 {1, 3, 5 ,7, 8}, 基数(不重复元素)为5。 基数估计就是在误差可接受的范围内,快速计算基数。

    5)pfadd命令并不会一次性分配12k内存,而是随着基数的增加而逐渐增加内存分配;而pfmerge操作则会将sourcekey合并后存储在12k大小的key中,这由hyperloglog合并操作的原理(两个hyperloglog合并时需要单独比较每个桶的值)可以很容易理解。

    6)Redis 对 HyperLogLog 的存储进行了优化,在计数比较小时,它的存储空间采用稀疏矩阵存储,空间占用很小,仅仅在计数慢慢变大,稀疏矩阵占用空间渐渐超过了阈值时才会一次性转变成稠密矩阵,才会占用 12k 的空间。 

应用场景

    a.   统计注册 IP 数

    b.   统计每日访问 IP 数

    c.   统计页面实时 UV 数

    d.   统计在线用户数

    e.   统计用户每天搜索不同词条的个数

说明:

    a.  基数不大,数据量不大就用不上,会有点大材小用浪费空间

    b.  有局限性,就是只能统计基数数量,而没办法去知道具体的内容是什么

    c.   和bitmap相比,属于两种特定统计情况,简单来说,HyperLogLog 去重比 bitmap 方便很多

     一般可以将bitmap和hyperloglog配合使用,bitmap标识哪些用户活跃,hyperloglog计数

     2、bitmap 位图(大数据处理)

     bitmap是什么?

     通过一个bit位来表示某个元素对应的值或者状态,其中的key就是对应元素本身。我们知道8个bit可以组成一个Byte,所以bitmap本身会极大的节省储存空间。

     说明:

     1) BIT位图不是实际的数据类型,而是在String类型上定义的一组面向位的操作。而String类型的key是二进制格式的,所以任意二进制格式的数据都可以作为key。Redis中是以8位二进制的方式存储。

     2) Redis从2.2.0版本开始新增了setbit,getbit,bitcount等几个bitmap相关命令。虽然是新命令,但是并没有新增新的数据类型,因为setbit等命令只不过是在set上的扩展

     常用命令:

      1)setbit

      SETBIT key offset value:给第offset位设置成value。当 key 不存在时,自动生成一个新的字符串值。

      

     注意:每次SETBIT完毕之后,有一个(integer) 0或者(integer)1的返回值,这个是在你进行SETBIT 之前,该offset位的比特值。

      2)getbit

      GETBIT命令: getbit key offset,获取指定offset下标的二进制,返回0或者1。当offset超过下标时,一直返回0。

      注意:offset是从左往右计数的,也就是从高位往低位。当超过位数时,结果是0。

       

     3)bitcount

      统计字符串被设置为1的bit数。

     BITCOUNT key [start end]  

     

     不指定start和end的情况下,bitcount会对整个该key对应的value字符串进行行计数。

     注意:

     1)统计指定key位置为1的数量(区间统计不建议使用,bitcount用的是byte来计算位数,其他setbit和getbit用的是bit

     2)bitCount虽然提供了start和end参数,但是这个说的是字节的位置,而不是对应"位"的位置。而redis中一个汉字占3个字节,一个英文字符占1个字节

     3)如果要指定区间,用bitcount并不是太合适,因为它的start或者end指的是第几个字节,不太好确定。不过,我们可以通过get把value取出来自己解析,一般情况下,这个value不会太大。

     比如下面这段代码:

 1 <?php
 2 // 字符串(中文)转化为二进制
 3 function StrToBin($str){
 4     $arr = preg_split('/(?<!^)(?!$)/u', $str);
 5     foreach($arr as &$v){
 6         $temp = unpack('H*', $v);
 7         $v = base_convert($temp[1], 16, 2);
 8         while($v<8)$v='0'.$v;
 9         unset($temp);
10     }
11     return join('',$arr);
12 }
13 
14 
15 $bin=StrToBin('中文');
16 echo $bin;
17 echo PHP_EOL;
18 echo substr_count($bin,'1');
19 
20 // 输出结果
21 // 111001001011100010101101111001101001011010000111
22 // 26

    使用场景:用户签到

     4)bitop

      使用时间作为cacheKey,然后用户ID为offset,如果当日活跃过就设置为1
      那么我该如果计算某几天/月/年的活跃用户呢(暂且约定,统计时间内只有有一天在线就称为活跃),有请下一个redis的命令

      BITOP operation destkey key [key ...]
     说明:

      1)对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上。

      2)BITOP 命令支持 AND 、 OR 、 NOT 、 XOR 这四种操作中的任意一种参数

      3)操作的时候,最短的那个字符串,转换二进制,位数不足的就在后面用0填充,直到与最长的字符串长度相等

      4)操作的结果,返回的是最长的那个字符串的长度

     

    使用场景:统计活跃用户

     3、GEO

     自Redis 3.2开始,Redis基于geohash和有序集合提供了地理位置相关功能。

      Redis Geo命令实现
      Redis将地理位置的52位GeoHash值作为有序集合的score,将地理位置存放在有序集合中进行保存。

      后续按位置搜索时,依据GeoHash的特性搜索当前方块与环绕当前方块的8个方块来搜索目标位置集合。Redis中接受的有效的精度范围为-180到180度,有效维度范围为-85.05112878到 85.05112878度(靠近南北极的一小块地方是无法生成索引的)。

      实现方式:
      Redis内部使用有序集合来保存key,每一个member的score大小为一个52位的Geohash值(double类型精度为52位)。
      实际上Redis内部实现的时候就是将GEOADD命令转换成ZADD命令来实现的。(这也解释了为什么没有专门的georem命令,地理位置信息是通过使用ZREM命令来删除成员。)

     常用命令:

     1) GEOADD key longitude latitude member [longitude latitude member ...]

     2) GEOPOS

     3) GEODIST key member1 member2 [m|km|ft|mi]    用于返回两个给定位置之间的距离,默认单位:m(米)

     4)GEORADIUS   以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。

     说明:

     WITHDIST: 在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。

     WITHCOORD: 将位置元素的经度和维度也一并返回。

     WITHHASH: 以 52 位有符号整数的形式, 返回位置元素经过原始 geohash 编码的有序集合分值。 这个选项主要用于底层应用或者调试, 实际中的作用并不大。

     COUNT 限定返回的记录数。

     ASC: 查找结果根据距离从近到远排序。

     DESC: 查找结果根据从远到近排序。

     5)GEORADIUSBYMEMBER :和GEORADIUS 命令一样, 都可以找出位于指定范围内的元素, 但是 GEORADIUSBYMEMBER 的中心点是由给定的位置元素决定的, 而不是使用经度和纬度来决定中心点。

     6)GEOHASH

     用于获取一个或多个位置元素的 geohash 值

      实现方式:

     Redis在内部生成有序集合成员score时的geohash值与标准的算法略有差异(Redis内部使用-85,85作为维度范围,标准使用-90,90)。

     这个命令返回的是标准值,与 https://en.wikipedia.org/wiki/Geohash 中标准算法和http://geohash.co/网站的计算结果一致。

 

 三、Stream

     这是Redis5.0引入的全新数据结构,用一句话概括Stream就是Redis实现的内存版kafka。

     Redis Stream 主要用于消息队列(MQ,Message Queue),Redis 本身是有一个 Redis 发布订阅 (pub/sub) 来实现消息队列的功能,但它有个缺点就是消息无法持久化,如果出现网络断开、Redis 宕机等,消息就会被丢弃。

     简单来说发布订阅 (pub/sub) 可以分发消息,但无法记录历史消息。

     消息队列相关命令:

XADD key ID field value [field value ...]    说明: ID 指的是消息 id,我们使用 * 表示由 redis 生成,可以自定义,但是要自己保证递增性。

XTRIM

XDEL

XLEN

XRANGE

XREVRANGE

XREAD

消费者组相关命令:

XGROUP CREATE

XREADGROUP GROUP

XACK

XGROUP SETID

XGROUP DELCONSUMER

XGROUP DESTROY

XPENDING

XCLAIM

XINFO

XINFO GROUPS

XINFO STREAM

 参考链接:

 https://developer.aliyun.com/article/62844

 https://segmentfault.com/a/1190000008188655

原文地址:https://www.cnblogs.com/hld123/p/14654305.html