Redis数据类型以及复杂度。
一、String
- 应用:String结构使用非常广泛、最常见的就是缓存用户信息。将用户信息结构体使用JSON序列化成字符串、存入redis中、获取时再将value反序列化成目标对象。
string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如jpg图片或者序列化的对象。 - 常用操作
- 储存 set key value 时间复杂度 O(1)
Max_:1>set username Max
- 获取 get key 时间复杂度 O(1)
Max_:1>get username "Max"
- 删除 del key 时间复杂度 O(k) k是键的个数
Max_:1>del username
- 先取值后塞值 getset key value 时间复杂度 O(1)
Max_:1>set name tom
"OK"
Max_:1>getset name jack
"tom"
- 追加值 append key value ;如果 key 已经存在,则直接在对应的 value 后追加值否则就创建新的键值对 时间复杂度 O(1)
Max_:1>append name lalal
"9"
Max_:1>get name
"jacklalal"
- 是否存在key exists key 存在返回1,否返回0 时间复杂度 O(1)
Max_:1>exists name
"1"
二、List
- 应用:Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。
- 常用操作
- 将元素添加到列表的左边:lpush key value 时间复杂度 O(k) k是field的个数
Max_:3>lpush mylist a
"1"
Max_:3>lpush mylist b
"2"
- 将元素添加到列表的右边:rpush key value 时间复杂度 O(k) k是field的个数
Max_:3>rpush mylist c
"3"
Max_:3>rpush mylist d
"4"
- 范围获取:lrange key start end 时间复杂度O(s+n),s是start的偏移量,n是start到end的范围
Max_:3>lrange mylist 0 3
1) "b"
2) "a"
3) "c"
4) "d"
- 删除并返回列表左边的元素: 时间复杂度 O(1)
Max_:3>lpop mylist
"b"
- 删除并返回列表右边的元素: 时间复杂度 O(1)
Max_:3>rpop mylist
"d"
- 根据参数 count 的值,移除列表中与参数 value 相等的元素。 LREM key count value 时间复杂度 O(1)
- 将列表 key 下标为 index 的元素的值设置为 value 。 LSET key index value 时间复杂度 O(n) n是索引的偏移量
- 返回列表 key 的长度。 LLEN key 时间复杂度 O(1)
- 对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。 LTRIM key start stop 时间复杂度O(n) n是索引的偏移量==
- 返回列表 key 中,下标为 index 的元素。 LINDEX key index 时间复杂度O(n) n是索引的偏移量
三、Hash
- 应用:hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。
- 常用操作
- 存储 hset key field value 时间复杂度 O(1)
Max_:2>hset myhash username lisi
"0"
- 获取指定field对应的value:hget key field 时间复杂度 O(1)
Max_:2>hget myhash username
"lisi"
- 获取所有的field和value:hgetall key 时间复杂度 0(k),k是field的个数
Max_:2>hgetall myhash
1) "username"
2) "lisi"
- 删除 hdel key field 时间复杂度 0(k),k是field的个数
Max_:2>hdel myhash username
"1"
- 获取key里面的键值对数量 hlen hash的key 时间复杂度 O(1)
- hexists:判断键值是否存在。hexists hash的key 项的key 时间复杂度 O(1)
- hkeys:获取所有的item的key,hkeys hash的key 时间复杂度 0(k),k是field的个数
- hincrby : 增减整数数字,:hincrby Hash的key 项的key 正负整数 时间复杂度 O(1)
四、Set
- 应用:Redis 的 Set 是 string 类型的无序集合。
集合是通过哈希表实现的。 - 常用操作
- 添加:sadd key value,可以写多个value 时间复杂度O(k),k为元素个数
Max_:4>sadd myset a b c d
"4"
Max_:4>sadd myset b c
"0"
- 获取set集合中所有元素:smembers key、 时间复杂度O(n),n为元素总数
Max_:4>smembers myset
1) "c"
2) "b"
3) "d"
4) "a"
- 删除某个元素:srem key value 时间复杂度O(k),k为元素个数
Max_:4>srem myset a
"1"
- 获取集合的成员数 scard key 时间复杂度 O(1)
- 移除并返回集合中的一个随机元素 spop key 时间复杂度 O(1)
- 移除集合中一个或多个成员 srem key member1 [member2] 时间复杂度O(k),k为元素个数
- 返回给定所有集合的交集 sinter key1 [key2] 时间复杂度O(m*k),k为多个集合中元素较少的个数,m是键个数
- 返回所有给定集合的并集 sunion key1 [key2] 时间复杂度O(k),k为多个集合元素个数和
五、Zset
- 应用:Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
zset的成员是唯一的,但分数(score)却可以重复。 - 常用操作
- 存储:zadd key score value 时间复杂度O(k*log(n)),k为添加 成员个数,n为当前成员个数
Max_:5>zadd mysort 1 Max
"1"
Max_:5>zadd mysort 2 Sex
"1"
Max_:5>zadd mysort 3 Tax
"1"
- 获取:zrange key start end [withscores] | zrange mysort 0 -1 withscores 时间复杂度O(log(n)),n为当前成员个数
Max_:5>zrange mysort 0 -1
1) "Max"
2) "Sex"
3) "Tax"
Max_:5>zrange mysort 0 -1 withscores
1) "Max"
2) "1"
3) "Sex"
4) "2"
5) "Tax"
6) "3"
- 删除:zrem key value 时间复杂度O(k*log(n)),k为删除成员个数,n为当前成员个数
Max_:5>zrem mysort Tax
"1"
- 对有序集合中指定成员的分数加上增量 increment 时间复杂度O(log(n)),n为当前成员个数
ZINCRBY key increment member - 获取有序集 key 的元素成员的个数 时间复杂度 O(1)
zcard key - 获取有序集 key 中,所有 score 值介于 min 和 max 之间(包括 min 和 max)的成员,有序 成员是按递增(从小到大)排序。 时间复杂度O(log(n)+k),k为要获取成员个数,n为当前成员个数
zrangebyscore key min max [WITHSCORES ] [LIMIT offset count]
六、bitmap
- 应用场景与简介:就是通过一个bit位来表示某个元素对应的值或者状态,其中的key就是对应元素本身。我们知道8个bit可以组成一个Byte,所以bitmap本身会极大的节省储存空间。 使用场景 <用户周活跃> <统计活跃用户> <用户在线状态> <用户签到>等
- 常用操作:
- 设置或者清空key的value(字符串)在offset处的bit值(只能只0或者1)。
Max_:6>setbit mytest1 8987129 0
"0"
Max_:6>setbit mytest1 8987129 1
"0"
- 对key1 key2做opecation并将结果保存在rs上 bitop operation rs key1 [key2…]
Max_:6>bitop OR result Monday Tuesday Wednesday Thursday Friday Saturday Sunday
"1123392"
- 对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上。
BITOP operation destkey key [key …]
- 参考
七、geohash
- 应用场景与简介: Redis 在 3.2 版本以后增加了地理位置 GEO 模块,意味着我们可以使用 Redis 来实现摩拜单车「附近的 Mobike」、美团和饿了么「附近的餐馆」这样的功能了。 业界比较通用的地理位置距离排序算法是 GeoHash 算法.GeoHash 算法将二维的经纬度数据映射到一维的整数,这样所有的元素都将在挂载到一条线上,距离靠近的二维坐标映射到一维后的点之间距离也会很接近。当我们想要计算「附近的人时」,首先将目标位置映射到这条线上,然后在这个一维的线上获取附近的点就行了。
底层zset - 常用操作:
- geoadd 指令携带集合名称以及多个经纬度名称三元组,注意这里可以加入多个三元组
127.0.0.1:6379> geoadd company 116.48105 39.996794 juejin
(integer) 1
127.0.0.1:6379> geoadd company 116.514203 39.905409 ireader
(integer) 1
127.0.0.1:6379> geoadd company 116.489033 40.007669 meituan
(integer) 1
127.0.0.1:6379> geoadd company 116.562108 39.787602 jd 116.334255 40.027400 xiaomi
(integer) 2
- geodist 指令可以用来计算两个元素之间的距离,携带集合名称、2 个名称和距离单位。
127.0.0.1:6379> geodist company juejin ireader km
"10.5501"
127.0.0.1:6379> geodist company juejin meituan km
"1.3878"
127.0.0.1:6379> geodist company juejin jd km
"24.2739"
127.0.0.1:6379> geodist company juejin xiaomi km
"12.9606"
127.0.0.1:6379> geodist company juejin juejin km
"0.0000"
- geopos 指令可以获取集合中任意元素的经纬度坐标,可以一次获取多个。
127.0.0.1:6379> geopos company juejin
"116.48104995489120483"
2) "39.99679348858259686"
127.0.0.1:6379> geopos company ireader
"116.5142020583152771"
2) "39.90540918662494363"
127.0.0.1:6379> geopos company juejin ireader
"116.48104995489120483"
2) "39.99679348858259686"
"116.5142020583152771"
2) "39.90540918662494363"
补充:我们观察到获取的经纬度坐标和 geoadd 进去的坐标有轻微的误差,原因是 geohash 对二维坐标进行的一维映射是有损的,通过映射再还原回来的值会出现较小的差别。对于「附近的人」这种功能来说,这点误差根本不是事。
- geohash 可以获取元素的经纬度编码字符串,上面已经提到,它是 base32 编码。 你可以使用这个编码值去 http://geohash.org/${hash}中进行直接定位,它是 geohash 的标准编码值。
127.0.0.1:6379> geohash company ireader
1) "wx4g52e1ce0"
127.0.0.1:6379> geohash company juejin
1) "wx4gd94yjn0"
- 参考文章
八、hyperloglog
- 应用场景与简介:
Redis 在 2.8.9 版本添加了 HyperLogLog 结构。Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。
在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。
基数不大,数据量不大就用不上,会有点大材小用浪费空间
有局限性,就是只能统计基数数量,而没办法去知道具体的内容是什么
和bitmap相比,属于两种特定统计情况,简单来说,HyperLogLog 去重比 bitmap 方便很多
一般可以bitmap和hyperloglog配合使用,bitmap标识哪些用户活跃,hyperloglog计数
适用于一下场景:
- 统计注册 IP 数
- 统计每日访问 IP 数
- 统计页面实时 UV 数
- 统计在线用户数
- 统计用户每天搜索不同词条的个数
- 理解:HyperLogLog是一种算法,并非redis独有。目的是做基数统计,故不是集合,不会保存元数据,只记录数量而不是数值。
耗空间极小,支持输入非常体积的数据量、核心是基数估算算法,主要表现为计算时内存的使用和数据合并的处理。最终数值存在一定误差。 - 常用操作:
- pfadd添加 影响基数估值则返回1否则返回0.若key不存在则创建 时间复杂度O(1)
127.0.0.1:6379> pfadd m1 1 2 3 4 1 2 3 2 2 2 2
(integer) 1
- pfcount 获取基数值 也就是去重值 (1,1,2,2,3)的插入pfcount得到的是3、可以一次统计多个key 时间复杂度为O(N) n为key的个数,返回值是一个带有0.81%标准错误。
127.0.0.1:6379> pfadd m1 1 2 3 4 1 2 3 2 2 2 2
(integer) 1
127.0.0.1:6379> pfcount m1
(integer) 4
- pfmerger合并多个key
取多个key的并集
命令只会返回OK
时间复杂度 O(N)
127.0.0.1:6379> pfadd m1 1 2 3 4 1 2 3 2 2 2 2
(integer) 1
127.0.0.1:6379> pfcount m1
(integer) 4
127.0.0.1:6379> pfadd m2 3 3 3 4 4 4 5 5 5 6 6 6 1
(integer) 1
127.0.0.1:6379> pfcount m2
(integer) 5
127.0.0.1:6379> pfmerge mergeDes m1 m2
OK
127.0.0.1:6379> pfcount mergeDes
(integer) 6
- 参考
九、streams
- 应用场景及简介:
Redis Stream 是 Redis 5.0 版本新增加的数据结构。Redis Stream 主要用于**消息队列**(MQ,Message Queue),Redis 本身是有一个 Redis 发布订阅 (pub/sub) 来实现消息队列的功能,但它有个缺点就是消息无法持久化,如果出现网络断开、Redis 宕机等,消息就会被丢弃。而 Redis Stream 提供了消息的持久化和主备复制功能,可以让任何客户端访问任何时刻的数据,并且能记住每一个客户端的访问位置,还能保证消息不丢失。 - 内容较多。深入理解。 见几篇参考文章
补充:什么是二进制安全
二进制安全 是指,在传输数据时,保证二进制数据的信息安全,也就是不被篡改、破译等,如果被攻击,能够及时检测出来。