书接上文:Redis 入门基础(一)
概览:本章节为 Redis
五大数据类型的使用方法笔记
文章目录
三、基础知识
-
Redis 数据库
Redis数据库有16个
# 连接redis服务 [root@localhost ~]# redis-cli -p 6379 127.0.0.1:6379 > ping PONG 127.0.0.1:6379 > SELECT 3 // 切换到3号数据库 OK 127.0.0.1:6379 > DBSIZE // 查看数据库大小 (integer) 4 127.0.0.1:6379 > KEYS * // 查看当前数据库所有的key 1) "mylist" 2) "myhash" 3) "counter:__rand_int__" 4) "key:__rand_int__" 127.0.0.1:6379 > FLUSHDB //清空当前数据库 OK 127.0.0.1:6379 > KEYS * (empty array) 127.0.0.1:6379 > FLUSHALL //清空全部数据库 OK
-
Redis 线程
为什么 Redis 单线程性能还这么好?
- Redis 将数据存放在内存中,基于内存操作,单线程执行效率高。(多线程执行时,CPU上下文切换会增加耗时)
- Redis的性能瓶颈不是CPU,而是机器的内存和网络I/O
为什么Redis 6.0 引入多线程?
- 在读写网络的 read/write 系统调用执行期间会占用大部分CPU时间,当一些操作无法短时间内完成,后续操作就会被阻塞,而多线程可以让网络处理请求并发进行,一定程度上能防止阻塞,提升性能。
- 多线程除了可以减少由于网络 I/O 等待造成的影响,还可以充分利用 CPU 的多核优势。
-
Redis 键(Key)
[root@localhost ~]# redis-cli -p 6379 127.0.0.1:6379 > KEYS * // 查看所有的KEY (empty array) 127.0.0.1:6379 > set name hello // 设置KEY OK 127.0.0.1:6379 > get name // 获取 KEY 值 "hello" ------------------------------------ 127.0.0.1:6379 > EXISTS name // 查看当前的 KEY 是否存在 (integer) 1 // 存在为1 127.0.0.1:6379 > EXISTS name1 (integer) 0 // 不存在为0 ------------------------------------ 127.0.0.1:6379 > move name 1 // 将 KEY 值移动到 1 号数据库 (integer) 1 127.0.0.1:6379 > SELECT 1 // 选择 1 号数据库 OK 127.0.0.1:6379[1] > KEYS * 1) "name" ------------------------------------ 127.0.0.1:6379 > SET name hello OK 127.0.0.1:6379 > EXPIRE name 10 // 设置 KEY 值的过期时间 (integer) 1 127.0.0.1:6379 > ttl name // 查看 KEY 值的剩余时间 (integer) 9 127.0.0.1:6379 > ttl name (integer) -2 // -2 为已过期 ------------------------------------ 127.0.0.1:6379 > SET name hello OK 127.0.0.1:6379 > TYPE name // 查看 KEY 值的类型 string
四、数据类型
1. String (字符串)
参考文章:Redis 字符串(String)
-
命令
------------------------------------ # STRLEN key 如果 key 已经存在并且是一个字符串, APPEND 命令将指定的 value 追加到该 key 原来值(value)的末尾 如果 key 不存在,就相当于SET一个KEY ------------------------------------ 127.0.0.1:6379 > APPEND name "hello1" // 追加字符串, (integer) 11 // 返回值为字符串长度 127.0.0.1:6379 > get name "hellohello1" ------------------------------------ # STRLEN key 返回 key 所储存的字符串值的长度 ------------------------------------ 127.0.0.1:6379 > STRLEN name // 获取字符串长度 (integer) 11 // 返回值为字符串长度 ------------------------------------ # INCR key # DECR key 将 key 中储存的数字值增一、减一 ------------------------------------ 127.0.0.1:6379 > set views 0 OK 127.0.0.1:6379 > get views "0" 127.0.0.1:6379 > INCR views // 自增1 (integer) 1 127.0.0.1:6379 > get views "1" 127.0.0.1:6379 > DECR views // 自减1 (integer) 0 127.0.0.1:6379 > get views "0" ------------------------------------ # INCRBY key increment # DECRBY key decrement 将 key 所储存的值加上给定的增量值(increment)、减量值(decrement) ------------------------------------ 127.0.0.1:6379 > INCRBY views 10 // 设置步长,指定自增量 (integer) 10 127.0.0.1:6379 > DECRBY views 10 // 设置步长,指定自减量 (integer) 0 ------------------------------------ # GETRANGE key start end 返回 key 中字符串值的子字符 ------------------------------------ 127.0.0.1:6379 > set key1 hello,redis OK 127.0.0.1:6379 > get key1 "hello,redis" 127.0.0.1:6379 > GETRANGE key1 0 4 // 截取[0-4]个字符串 "hello" 127.0.0.1:6379 > GETRANGE key1 6 11 // 截取[6-11]个字符串 "redis" 127.0.0.1:6379 > GETRANGE key1 0 -1 // 截取全部字符串 = get key "hello,redis" ------------------------------------ # SETRANGE key offset value 用 value 参数替换给定 key 所储存的字符串值 ------------------------------------ 127.0.0.1:6379 > get key1 "hello,redis" 127.0.0.1:6379 > SETRANGE key1 6 world // 替换指定位置开始的字符串 (integer) 11 127.0.0.1:6379 > get key1 "hello,world" ------------------------------------ # SETEX key seconds value 将 key 的过期时间设为 seconds ------------------------------------ 127.0.0.1:6379 > SETEX key2 30 "hello" OK 127.0.0.1:6379 > get key2 "hello" 127.0.0.1:6379 > ttl key2 (integer) 20 ------------------------------------ # SETNX key value 只有在 key 不存在时设置 key 的值 ------------------------------------ 127.0.0.1:6379 > SETNX key3 "redis" // 如果 key3 不存在则创建 (integer) 1 127.0.0.1:6379 > SETNX key3 "hello" // key3 存在,创建失败 (integer) 0 127.0.0.1:6379 > get key3 "redis" ------------------------------------ # MSET key value [key value ...] 同时设置一个或多个 key-value 对 # MGET key [key ...] 获取所有(一个或多个)给定 key 的值 # MSETNX key value [key value ...] 同时设置一个或多个 key-value 对, 要么一起成功,要么一起失败 ------------------------------------ 127.0.0.1:6379 > MSET k1 v1 k2 v2 k3 v3 OK 127.0.0.1:6379 > KEYS * 1) "k1" 2) "k2" 3) "k3" 127.0.0.1:6379 > MGET k1 k2 k3 1) "v1" 2) "v2" 3) "v3" 127.0.0.1:6379 > MSETNX k1 v1 k4 v4 (integer) 0 127.0.0.1:6379 > keys * 1) "k1" 2) "k2" 3) "k3" ------------------------------------ # GETSET key value 将给定 key 的值设为 value ,并返回 key 的旧值(old value) ------------------------------------ 127.0.0.1:6379 > GETSET db redis (nil) 127.0.0.1:6379 > get db "redis" 127.0.0.1:6379 > GETSET db mongodb "redis" 127.0.0.1:6379 > get db "mongdb"
-
应用
# 设置一个 user:1 对象,值为 json 字符来保存对象 # 这里的 key 格式是 user:{id}:{field} 127.0.0.1:6379 > set user:1 {name:zhangsan,age:3,sex:1,other:none} OK 127.0.0.1:6379 > mset user:1:name zhangsan user:1:age 2 OK 127.0.0.1:6379 > MGET user:1:name user:1:age 1) "zhangsan" 2) "2"
2. List(列表)
List可以理解为双端队列,可以从两端出队和入队
参考文章:Redis 列表(List)
-
命令
------------------------------------ # LPUSHX key value 将一个值插入到已存在的列表头部(可以理解为链表的头插法) ------------------------------------ 127.0.0.1:6379 > LPUSH list one (integer) 1 127.0.0.1:6379 > LPUSH list two three (integer) 3 127.0.0.1:6379 > LRANGE list 0 -1 1) "three" 2) "two" 3) "one" ------------------------------------ # RPUSH key value1 [value2] 在列表中添加一个或多个值(可以理解为链表的尾插法) ------------------------------------ 127.0.0.1:6379 > RPUSH list right (integer) 4 127.0.0.1:6379 > LRANGE list 0 -1 1) "three" 2) "two" 3) "one" 4) "right" ------------------------------------ # LPOP key 移除并获取列表的第一个元素,返回值为移除的元素 # RPOP key 移除列表的最后一个元素,返回值为移除的元素。 ------------------------------------ 127.0.0.1:6379 > LRANGE list 0 -1 1) "three" 2) "two" 3) "one" 4) "right" 127.0.0.1:6379 > LPOP list "three" 127.0.0.1:6379 > LRANGE list 0 -1 1) "two" 2) "one" 3) "right" 127.0.0.1:6379 > RPOP list "right" 127.0.0.1:6379 > LRANGE list 0 -1 1) "two" 2) "one" ------------------------------------ # LINDEX key index 通过下标获取列表中的元素 ------------------------------------ 127.0.0.1:6379 > LRANGE list 0 -1 1) "two" 2) "one" 127.0.0.1:6379 > LINDEX list 0 "two" 127.0.0.1:6379 > LINDEX list 1 "one" ------------------------------------ # LLEN key 获取列表长度 ------------------------------------ 127.0.0.1:6379 > LLEN list (integer) 2 ------------------------------------ # LREM key count value 移除列表元素 ------------------------------------ 127.0.0.1:6379 > LREM list 1 one (integer) 1 127.0.0.1:6379 > LRANGE list 0 -1 1) "three" 2) "three" 3) "one" 4) "two" 127.0.0.1:6379 > LREM list 2 three (integer) 2 ------------------------------------ # LTRIM key start stop 对一个列表进行修剪(trim), 让列表只保留指定区间内的元素, 不在指定区间之内的元素都将被删除 ------------------------------------ 127.0.0.1:6379 > RPUSH redislist hello hello1 hello2 hello3 (integer) 4 127.0.0.1:6379 > LRANGE redislist 0 -1 1) "hello" 2) "hello1" 3) "hello2" 4) "hello3" 127.0.0.1:6379 > LTRIM redislist 1 2 // 通过下标截取指定长度 OK 127.0.0.1:6379 > LRANGE redislist 0 -1 1) "hello1" 2) "hello2" ------------------------------------ # RPOPLPUSH source destination 移除列表的最后一个元素 并将该元素添加到另一个列表并返回 ------------------------------------ 127.0.0.1:6379 > RPUSH redislist hello hello1 hello2 (integer) 3 127.0.0.1:6379 > RPOPLPUSH redislist newlist "hello2" 127.0.0.1:6379 > LRANGE redislist 0 -1 1) "hello" 2) "hello1" 127.0.0.1:6379 > LRANGE newlist 0 -1 1) "hello2" ------------------------------------ # LSET key index value 通过下标设置列表元素的值 ------------------------------------ 127.0.0.1:6379 > LRANGE redislist 1 1 1) "hello1" 127.0.0.1:6379 > LSET redislist 1 newhello OK 127.0.0.1:6379 > LRANGE redislist 1 1 1) "newhello" ------------------------------------ # LINSERT key BEFORE|AFTER pivot value 在列表的元素前或者后插入元素 ------------------------------------ 127.0.0.1:6379 > RPUSH list hello0 hello1 hello2 hello4 (integer) 4 127.0.0.1:6379 > LINSERT list before hello4 hello3 (integer) 5 127.0.0.1:6379 > LRANGE list 0 -1 1) "hello0" 2) "hello1" 3) "hello2" 4) "hello3" 5) "hello4" 127.0.0.1:6379 > LINSERT list after hello4 hello5 (integer) 6 127.0.0.1:6379 > LRANGE list 0 -1 1) "hello0" 2) "hello1" 3) "hello2" 4) "hello3" 5) "hello4" 6) "hello5"
-
应用
消息队列、栈、
-
小结
List
实际上是一个链表,before after left right都可以插入- 如果
key
不存在,则创建新链表 - 如果
key
存在,则添加新内容 - 在两端操作效率高,操作中间元素效率相对低
3. Set(集合)
参考文章:Redis 集合(Set)
Set 是 String 类型的无序集合。集合成员是唯一的,不能出现重复的数据
-
命令
------------------------------------ # SADD key member1 [member2] 向集合添加一个或多个成员 # SMEMBERS key 返回集合中的所有成员 # SCARD key 获取集合的成员数 ------------------------------------ 127.0.0.1:6379 > SADD set hello0 hello1 hello2 (integer) 3 127.0.0.1:6379 > SADD set "hello0" (integer) 0 127.0.0.1:6379 > SCARD set (integer) 4 127.0.0.1:6379 > SMEMBERS set 1) "hello" 2) "hello2" 3) "hello1" 4) "hello0" ------------------------------------ # SISMEMBER key member 判断 member 元素是否是集合 key 的成员 ------------------------------------ 127.0.0.1:6379 > SISMEMBER set hello (integer) 1 127.0.0.1:6379 > SISMEMBER set world (integer) 0 ------------------------------------ # SREM key member1 [member2] 移除集合中一个或多个成员 ------------------------------------ 127.0.0.1:6379 > SREM set hello0 (integer) 1 127.0.0.1:6379 > SREM set hello1 hello2 (integer) 2 127.0.0.1:6379 > SMEMBERS set 1) "hello" ------------------------------------ # SRANDMEMBER key [count] 返回集合中一个或多个随机数 # SPOP key 移除并返回集合中的一个随机元素 ------------------------------------ 127.0.0.1:6379 > SADD set hello0 hello1 hello2 hello3 (integer) 4 127.0.0.1:6379 > SRANDMEMBER set 1 1) "hello0" 127.0.0.1:6379 > SRANDMEMBER set 2 1) "hello3" 2) "hello0" 127.0.0.1:6379 > SPOP set "hello1" 127.0.0.1:6379 > SMEMBERS set 1) "hello3" 2) "hello2" 3) "hello0" ------------------------------------ # SMOVE source destination member 将 member 元素从 source 集合移动到 destination 集合 ------------------------------------ 127.0.0.1:6379 > SADD set hello0 hello1 hello2 hello3 (integer) 4 127.0.0.1:6379 > SMEMBERS set 1) "hello3" 2) "hello2" 3) "hello1" 4) "hello0" 127.0.0.1:6379 > sadd set1 hi0 hi1 (integer) 2 127.0.0.1:6379 > SMOVE set set1 hello0 (integer) 1 127.0.0.1:6379 > SMEMBERS set1 1) "hi0" 2) "hi1" 3) "hello0" ------------------------------------ # SDIFF key1 [key2] 返回第一个集合与其他集合之间的差异。 # SINTER key1 [key2] 返回给定所有集合的交集 # SUNION key1 [key2] 返回所有给定集合的并集 ------------------------------------ 127.0.0.1:6379 > SADD key1 a b c (integer) 3 127.0.0.1:6379 > SADD key2 c d e (integer) 3 127.0.0.1:6379 > SDIFF key1 key2 1) "b" 2) "a" 127.0.0.1:6379 > SINTER key1 key2 1) "c" 127.0.0.1:6379 > SUNION key1 key2 1) "b" 2) "a" 3) "c" 4) "e" 5) "d"
-
应用
社交软件上,将用户的关注列表设置在 follow 集合中,粉丝列表设置在 fans 集合中
set
集合可以实现共同关注、共同好友、推荐好友等功能
4. Hash(哈希)
参考文章:Redis 哈希(Hash)
hash 是 string 类型的 字段 和 值 的映射表,适用于存储对象。
-
命令
------------------------------------ # HSET key field value 将哈希表 key 中的字段 field 的值设为 value # HGET key field 获取存储在哈希表中指定字段的值。 # HMGET key field1 [field2] 获取所有给定字段的值 # HGETALL key 获取在哈希表中指定 key 的所有字段和值 PS: HMSET在Redis4.0 中被视为以启用,可使用HSET替代 ------------------------------------ 127.0.0.1:6379 > HSET hash field0 value0 (integer) 1 127.0.0.1:6379 > HSET hash field1 value1 field2 value2 (integer) 2 127.0.0.1:6379 > HGET hash field0 "value0" 127.0.0.1:6379 > HMGET hash field0 field1 1) "value0" 2) "value1" 127.0.0.1:6379 > HGETALL hash 1) "field0" 2) "value0" 3) "field1" 4) "value1" 5) "field2" 6) "value2" ------------------------------------ # HDEL key field1 [field2] 删除一个或多个哈希表字段 ------------------------------------ 127.0.0.1:6379 > HDEL hash field2 (integer) 1 127.0.0.1:6379 > HGETALL hash 1) "field0" 2) "value0" 3) "field1" 4) "value1" ------------------------------------ # HLEN key 获取哈希表中字段的数量 ------------------------------------ 127.0.0.1:6379 > HGETALL hash 1) "field0" 2) "value0" 3) "field1" 4) "value1" 127.0.0.1:6379 > HLEN hash (integer) 2 ------------------------------------ # HEXISTS key field 查看哈希表 key 中指定的字段是否存在 ------------------------------------ 127.0.0.1:6379 > HGETALL hash 1) "field0" 2) "value0" 3) "field1" 4) "value1" 127.0.0.1:6379 > HEXISTS hash field (integer) 0 127.0.0.1:6379 > HEXISTS hash field0 (integer) 1 ------------------------------------ # HKEYS key 获取所有哈希表中的field # HVALS key 获取哈希表中所有value ------------------------------------ 127.0.0.1:6379 > HGETALL hash 1) "field0" 2) "value0" 3) "field1" 4) "value1" 127.0.0.1:6379 > HKEYS hash 1) "field0" 2) "field1" 127.0.0.1:6379 > HVALS hash 1) "value0" 2) "value1" ------------------------------------ # HINCRBY key field increment 为哈希表 key 中的指定字段的整数值加上增量 increment ------------------------------------ 127.0.0.1:6379 > HSET hash field2 10 (integer) 1 127.0.0.1:6379 > HINCRBY hash field2 5 (integer) 15 127.0.0.1:6379 > HGET hash field2 "15" 127.0.0.1:6379 > HINCRBY hash field2 -1 (integer) 14 127.0.0.1:6379 > HGET hash field2 "14" ------------------------------------ # HSETNX key field value 只有在字段 field 不存在时,设置哈希表字段的值 ------------------------------------ 127.0.0.1:6379 > HGETALL hash 1) "field0" 2) "value0" 3) "field1" 4) "value1" 5) "14" 127.0.0.1:6379 > HSETNX hash field0 value1 (integer) 0 127.0.0.1:6379 > HSETNX hash field9 value9 (integer) 1
-
应用
hash 可以存放经常变更的数据,适合于对象的存储
例如社交软件中的用户信息user_name
,name
,age
5. Zset(有序集合)
Zset 是在 Set 的基础上增加了一个
double
类型score
值,Redis 通过score
来进行从小到大的排序
-
命令
------------------------------------ # ZADD key score1 member1 [score2 member2] 向有序集合添加一个或多个成员,或者更新已存在成员的分数 # ZCARD key 获取有序集合的成员数 # ZRANGE key start stop [WITHSCORES] 通过下标区间返回有序集合指定区间内的成员 # ZREM key member [member ...] 移除有序集合中的一个或多个成员 ------------------------------------ 127.0.0.1:6379 > ZADD salary 1000 xiaohong 2000 xiaoming 3000 zhangsan 4000 lisi (integer) 4 127.0.0.1:6379 > ZCARD salary (integer) 4 127.0.0.1:6379 > ZRANGE salary 0 -1 1) "xiaohong" 2) "xiaoming" 3) "zhangsan" 4) "lisi" 127.0.0.1:6379 > ZREM salary lisi (integer) 1 127.0.0.1:6379 > ZRANGE salary 0 -1 1) "xiaohong" 2) "xiaoming" 3) "zhangsan" ------------------------------------ # ZRANGE key start stop [WITHSCORES] 通过索引区间返回有序集合指定区间内的成员,分数从低到高 # ZREVRANGE key start stop [WITHSCORES] 通过索引区间有序集中指定区间内的成员,分数从高到低 ------------------------------------ 127.0.0.1:6379 > ZRANGE salary 0 -1 1) "xiaohong" 2) "xiaoming" 3) "zhangsan" // -inf 为 负无穷 +inf 为正无穷,意思是从最小到最大排序 127.0.0.1:6379 > ZRANGEBYSCORE salary -inf +inf 1) "xiaohong" 2) "xiaoming" 3) "zhangsan" // 按从最小到最大排序,并返回 score 值 127.0.0.1:6379 > ZRANGEBYSCORE salary -inf +inf withscores 1) "xiaohong" 2) "1000" 3) "xiaoming" 4) "2000" 5) "zhangsan" 6) "3000" // 按从最小到2000排序,并返回 score 值 127.0.0.1:6379 > ZRANGEBYSCORE salary -inf 2000 withscores 1) "xiaohong" 2) "1000" 3) "xiaoming" 4) "2000" // 从按分数从大到小排序 127.0.0.1:6379 > ZREVRANGE salary 0 -1 1) "zhangsan" 2) "xiaoming" 3) "xiaohong" // 从按分数从大到小排序,并返回 score 值 127.0.0.1:6379 > ZREVRANGEBYSCORE salary +inf -inf withscores 1) "zhangsan" 2) "3000" 3) "xiaoming" 4) "2000" 5) "xiaohong" 6) "1000" ------------------------------------ # ZCOUNT key min max 计算在有序集合中指定区间分数的成员数 ------------------------------------ 127.0.0.1:6379 > ZCOUNT salary 1000 2000 (integer) 2
-
应用
可以存储班级成绩列表、工资表排序、热搜榜等
或设置消息权重,例如:普通消息1,重要消息2
五、三种特殊数据类型
1. Geospatital(地理空间)
Geospatital 简称为 GEO ,主要用于存储和操作地理位置信息。
-
GEOADD
添加地理位置的坐标[经度(longitude)、纬度(latitude)、名称]PS: 地球两极无法直接添加,一般会下载数据用程序直接导入
**------------------------------------** **# GEOADD key longitude latitude member [longitude latitude member ...] ------------------------------------** 127.0.0.1:6379 > GEOADD CHINA:CITY:GEO 113.280 23.125 guangzhou (integer) 1 127.0.0.1:6379 > GEOADD CHINA:CITY:GEO 113.552 22.255 zhuhai (integer) 1 127.0.0.1:6379 > GEOADD CHINA:CITY:GEO 114.085 22.547 shenzhen (integer) 1
-
GEOPOS
获取地理位置的坐标**------------------------------------** **# GEOPOS key member [member ...]** **------------------------------------** 127.0.0.1:6379 > GEOPOS CHINA:CITY:GEO guangzhou zhuhai shenzhen 1) 1) "113.27999979257583618" 2) "23.12500000786719312" 2) 1) "113.55200260877609253" 2) "22.25500006018381072" 3) 1) "114.08500045537948608" 2) "22.54699993773966327"
-
geodist
计算两个位置之间的距离**------------------------------------** **# GEODIST key member1 member2 [m|km|ft|mi] ------------------------------------** 127.0.0.1:6379 > GEODIST CHINA:CITY:GEO guangzhou zhuhai "100711.9961" 127.0.0.1:6379 > GEODIST CHINA:CITY:GEO guangzhou zhuhai kM "100.7120"
-
georadius
根据给定的经纬度坐标来获取指定范围内的地理位置集合georadiusbymember
根据储存在位置集合里面的某个地点获取指定范围内的地理位置集合**------------------------------------** **# GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key] ------------------------------------** // 以经纬度 113 23 为中心,方圆110km的城市 ****127.0.0.1:6379 > GEORADIUS CHINA:CITY:GEO 113 23 110 km 1) "guangzhou" 2) "zhuhai" // 以经纬度 113 23 为中心,方圆110km的城市,并返回其经纬度和距离 127.0.0.1:6379 > GEORADIUS CHINA:CITY:GEO 113 23 110 km withcoord withdist 1) 1) "guangzhou" 2) "31.8492" 3) 1) "113.27999979257583618" 2) "23.12500000786719312" 2) 1) "zhuhai" 2) "100.3889" 3) 1) "113.55200260877609253" 2) "22.25500006018381072" **------------------------------------** **# GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key] ------------------------------------** // 以深圳为中心,查找方圆100km的城市 ****127.0.0.1:6379 > GEORADIUSBYMEMBER CHINA:CITY:GEO shenzhen 100 KM 1) "zhuhai" 2) "shenzhen" // 以深圳为中心,查找方圆100km的城市,并返回其经纬度和距离 127.0.0.1:6379 > GEORADIUSBYMEMBER CHINA:CITY:GEO shenzhen 100 KM withcoord withdist 1) 1) "zhuhai" 2) "63.7097" 3) 1) "113.55200260877609253" 2) "22.25500006018381072" 2) 1) "shenzhen" 2) "0.0000" 3) 1) "114.08500045537948608" 2) "22.54699993773966327"
-
geohash
返回一个或多个位置对象的 geohash 值将二维的经纬度信息转换为一维的字符串,字符串相同程度越高,相距越近
**------------------------------------** **# GEOHASH key member [member ...]** **------------------------------------** 127.0.0.1:6379 > GEOHASH CHINA:CITY:GEO shenzhen hangzhou 1) "ws10k0d1v10" 2) "wtmkq1sdxc0"
GEO 底层的实现原理是Zset,则可以使用Zset命令来操作 GEO
-
ZRANGE
可以查看 GEO 键中的值127.0.0.1:6379 > ZRANGE CHINA:CITY:GEO 0 -1 1) "zhuhai" 2) "shenzhen" 3) "guangzhou" 4) "hangzhou"
-
ZREM
可以删除 GEO 键中的值127.0.0.1:6379 > ZREM CHINA:CITY:GEO shenzhen (integer) 1 127.0.0.1:6379 > ZRANGE CHINA:CITY:GEO 0 -1 1) "zhuhai" 2) "guangzhou" 3) "hangzhou"
2. HyperLogLog(基数统计)
什么是基数?
设A {1, 3, 5, 7, 5, 7, 9},则A的基数集为 {1, 3, 5 ,7, 9}
基数(即为不重复的数)为5,可接受误差
HyperLogLog 使用场景
HyperLogLog 是一种数据结构,是用来做基数统计的算法。
例如:统计网页的访问量(每个ID只算作一个访问量)
传统方案可以使用 Set
保存用户ID(不会出现重复元素),然后统计 set
中的元素数量作为判断标准,但大量保存用户ID会浪费资源。
HyperLogLog 的优势:
- 每个HyperLogLog 只占用 12KB 内存
- 可以计算 2^64 个不同元素的基数(但有0.81%的错误率)
HyperLogLog 用法
-
PFADD
添加指定元素到 HyperLogLog 中**------------------------------------** **# PFADD key element [element ...]** **------------------------------------** 127.0.0.1:6379 > PFADD hyper a b c d e f g h i (integer) 1 127.0.0.1:6379 > PFADD hyper1 h i j k l m n (integer) 1
-
PFCOUNT
返回给定 HyperLogLog 的基数估算值**------------------------------------** **# PFCOUNT key [key ...]** **------------------------------------** 127.0.0.1:6379 > PFCOUNT hyper (integer) 9 127.0.0.1:6379 > PFCOUNT hyper1 (integer) 7
-
PFMERGE
将多个 HyperLogLog 合并为一个 HyperLogLog**------------------------------------** **# PFMERGE destkey sourcekey [sourcekey ...]** **------------------------------------** // 将hyper和hyper1合并到hyper2中 127.0.0.1:6379 > PFMERGE hyper2 hyper hyper1 OK 127.0.0.1:6379 > PFCOUNT hyper2 (integer) 14
3. Bitmap(位图)
Bitmap 是什么
Bitmap 是一种数据结构,是通过操作二进制位(位运算)来进行记录的,只有0和1两种状态
Bitmap 使用场景
适用于只有两种情况的场景:登录&未登录,打卡&未打卡,活跃&未活跃等
假设使用 Bitmap 来记录每周的打卡记录
第一位表示星期(0-6 周日-周六)
第二位表示是否打卡(0为未打卡,1为打卡)
-
SETBIT
设置 key 的 value**------------------------------------** **# SETBIT key offset value** **------------------------------------** // 设置每日打卡情况 127.0.0.1:6379 > SETBIT sign 0 0 // 周日 0 (integer) 0 127.0.0.1:6379 > SETBIT sign 1 1 // 周一 1 (integer) 0 127.0.0.1:6379 > SETBIT sign 2 1 // 周二 1 (integer) 0 127.0.0.1:6379 > SETBIT sign 3 1 // .... (integer) 0 127.0.0.1:6379 > SETBIT sign 4 1 (integer) 0 127.0.0.1:6379 > SETBIT sign 5 1 (integer) 0 127.0.0.1:6379 > SETBIT sign 6 1 (integer) 0
-
GETBIT
查看 key 的 value**------------------------------------ # GETBIT key offset ------------------------------------** // 获取指定日的打卡情况 127.0.0.1:6379 > SETBIT sign 6 1 (integer) 0 127.0.0.1:6379 > GETBIT sign 6 (integer) 1
-
BITCOUNT
统计 key 的 value------------------------------------ # BITCOUNT key [start end [BYTE|BIT]] ------------------------------------ // 统计周的打卡情况 127.0.0.1:6379 > BITCOUNT sign (integer) 6