Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。
关于RedisKey的基本命令
127.0.0.1:6379> set name jia
OK
127.0.0.1:6379> exists name # 判断当前key是否存在
(integer) 1 # 存在
127.0.0.1:6379> exists name1
(integer) 0 # 不存在
127.0.0.1:6379> move name 1 # 把当前的key移除到1号数据库
(integer) 1
127.0.0.1:6379> keys * # 查看所有的key
(empty array)
127.0.0.1:6379> set name jia
OK
127.0.0.1:6379> expire name 10 # 设置当前key的过期时间为10秒
(integer) 1
127.0.0.1:6379> ttl name # 查看当前key的剩余时间
(integer) 6
127.0.0.1:6379> ttl name
(integer) 2
127.0.0.1:6379> ttl name
(integer) -2 # 已过期
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379> set name jia
OK
127.0.0.1:6379> type name # 查看当前key的类型
string # string 类型
String(字符串)
设置值、获取值、判断是否存在、追加字符串、查看长度
127.0.0.1:6379> set name jia # 设置值
OK
127.0.0.1:6379> get name # 获得值
"jia"
127.0.0.1:6379> keys * # 获得所有的key
1) "name"
127.0.0.1:6379> exists name # 判断当前key是否存在
(integer) 1
127.0.0.1:6379> append name "yuguang" # 在当前key后面追加字符串(如果当前key不存在,就相当于set key)
(integer) 10
127.0.0.1:6379> get name
"jiayuguang"
127.0.0.1:6379> strlen name # 查看当前key的长度
(integer) 10
127.0.0.1:6379> append name ",love"
(integer) 15
127.0.0.1:6379> strlen name
(integer) 15
127.0.0.1:6379> get name
"jiayuguang,love"
自增、自减
i++ 步长 i+=
127.0.0.1:6379> set views 0 # 初始浏览量为0
OK
127.0.0.1:6379> get views
"0"
127.0.0.1:6379> incr views # 自增1 浏览量+1
(integer) 1
127.0.0.1:6379> incr views
(integer) 2
127.0.0.1:6379> get views
"2"
127.0.0.1:6379> decr views # 自减1 浏览量-1
(integer) 1
127.0.0.1:6379> decr views
(integer) 0
127.0.0.1:6379> decr views
(integer) -1
127.0.0.1:6379> get views
"-1"
127.0.0.1:6379> incrby views 10 # 自增10 浏览量+10 (可以设置步长)
(integer) 9
127.0.0.1:6379> incrby views 10
(integer) 19
127.0.0.1:6379> get views
"19"
127.0.0.1:6379> decrby views 10 # 自减10 浏览量-10 (可以设置步长)
(integer) 9
127.0.0.1:6379> get views
"9"
127.0.0.1:6379> set a 1
OK
127.0.0.1:6379> incrbyfloat a 1.1 # 自增 1.1 (可以设置浮点数步长)
"2.1"
127.0.0.1:6379> incrbyfloat a -1.6 # 自增-1.6 (可以设置浮点数步长)
"0.5"
字符串范围
获取范围内字符串
127.0.0.1:6379> set key1 "jiayuguang"
OK
127.0.0.1:6379> get key1
"jiayuguang"
127.0.0.1:6379> getrange key1 0 3 # 获取字符串[0,3]
"jiay"
127.0.0.1:6379> getrange key1 0 -1 # 获取全部字符串(和 get key是一样的)
"jiayuguang"
替换范围内字符串
127.0.0.1:6379> set key2 abcdefg
OK
127.0.0.1:6379> get key2
"abcdefg"
127.0.0.1:6379> setrange key2 1 xx # 替换指定位置开始的字符串
(integer) 7
127.0.0.1:6379> get key2
"axxdefg"
设置过期时间、当前值存在(不存在)赋值
setex (set with expire) # 设置过期时间
setnx (set if not exist) # 不存在时设置 (在分布式锁中会常常使用!)
127.0.0.1:6379> setex key3 30 "hello" # 设置key3 的值为 hello,30秒后过期
OK
127.0.0.1:6379> ttl key3
(integer) 18
127.0.0.1:6379> setnx mykey "redis" # 如果mykey 不存在,创建mykey
(integer) 1
127.0.0.1:6379> keys *
1) "mykey"
2) "key2"
3) "key1"
127.0.0.1:6379> ttl key3
(integer) -2
127.0.0.1:6379> setnx mykey "hi" # mykey存在,创建失败!
(integer) 0
127.0.0.1:6379> get mykey
"redis"
同时设置(获取)多个值
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 # 同时设置多个值
OK
127.0.0.1:6379> keys *
1) "k2"
2) "k3"
3) "k1"
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 # msetnx 是一个原子性的操作,要么一起成功,要么一起失败!(存在的话,赋值失败)
(integer) 0
127.0.0.1:6379> get k4
(nil)
# 对象
# set user:1 {name:zhangsan,age:3} 设置一个user:1 对象 值为 json字符来保存一个对象!
# 这里的key是一个巧妙的设计: user:{id}:{filed} , 如此设计在Redis中是完全OK了!
127.0.0.1:6379> mset user:1:name xiaoyequ user:1:age 2
OK
127.0.0.1:6379> mget user:1:name user:1:age
1) "xiaoyequ"
2) "2"
先get然后在set
127.0.0.1:6379> getset db redis # 如果不存在值,则返回 nil
(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
"mongodb"
应用场景
数据结构是相同的!value除了是字符串还可以是数字!
计数器
统计多单位的数量
粉丝数
对象缓存存储!
List(链表)
在redis里面,我们可以把list玩成 ,栈、队列、阻塞队列
所有的list命令都是用 “l” 开头的,Redis不区分大小命令
把值插入到链表中(左/右)、获取值
127.0.0.1:6379> LPUSH list one # 将一个值或者多个值,插入到链表头部 (左)
(integer) 1
127.0.0.1:6379> LPUSH list two
(integer) 2
127.0.0.1:6379> LPUSH list three
(integer) 3
127.0.0.1:6379> LRANGE list 0 -1 # 获取list中值
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> LRANGE list 0 1 # 通过区间获取具体的值
1) "three"
2) "two"
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"
127.0.0.1:6379> lpushx list "left1"
(integer) 5
127.0.0.1:6379> lpushx list1 "left2" # 如果list1不存在则失败
(integer) 0
127.0.0.1:6379> rpushx list "right1"
(integer) 6
127.0.0.1:6379> rpushx list1 "right2" # 如果list1不存在则失败
(integer) 0
127.0.0.1:6379> LRANGE list 0 -1
1) "left1"
2) "three"
3) "two"
4) "one"
5) "right"
6) "right1"
返回列表的长度
127.0.0.1:6379> Lpush list one
(integer) 1
127.0.0.1:6379> Lpush list two
(integer) 2
127.0.0.1:6379> Lpush list three
(integer) 3
127.0.0.1:6379> Llen list # 返回链表的长度
(integer) 3
移除链表中的元素
127.0.0.1:6379> LRANGE list 0 -1
1) "three"
2) "two"
3) "one"
4) "right"
127.0.0.1:6379> Lpop list # 移除list的第一个元素
"three"
127.0.0.1:6379> Rpop list # 移除list的最后一个元素
"right"
127.0.0.1:6379> LRANGE list 0 -1
1) "two"
2) "one"
通过下标获得链表中的某一个值
127.0.0.1:6379> LRANGE list 0 -1
1) "two"
2) "one"
127.0.0.1:6379> lindex list 1 # 通过下标获得 list 中的某一个值!
"one"
127.0.0.1:6379> lindex list 0
"two"
移除指定的值
lrem :lrem list count value
- 如果 count 为0,则删除所有值等于value的节点;
- 如果count不为0,则先对count去绝对值,假设记为abs,然后从左到右删除不大于abs个等于value的节点
127.0.0.1:6379> LRANGE list 0 -1
1) "three"
2) "three"
3) "two"
4) "one"
127.0.0.1:6379> lrem list 1 one # 移除list集合中指定个数的value,精确匹配
(integer) 1
127.0.0.1:6379> LRANGE list 0 -1
1) "three"
2) "three"
3) "two"
127.0.0.1:6379> lrem list 1 three
(integer) 1
127.0.0.1:6379> LRANGE list 0 -1
1) "three"
2) "two"
127.0.0.1:6379> Lpush list three
(integer) 3
127.0.0.1:6379> lrem list 2 three
(integer) 2
127.0.0.1:6379> LRANGE list 0 -1
1) "two"
修改某个节点的值
127.0.0.1:6379> Rpush mylist "hello" "hello1" "hello2" "hello3" "hello4"
(integer) 5
127.0.0.1:6379> LRANGE mylist 0 -1
1) "hello"
2) "hello1"
3) "hello2"
4) "hello3"
5) "hello4"
127.0.0.1:6379> lset mylist 3 "xiaoyequ" # 设置链表下标为3的节点值为 xiaoyequ
OK
127.0.0.1:6379> LRANGE mylist 0 -1
1) "hello"
2) "hello1"
3) "hello2"
4) "xiaoyequ"
5) "hello4"
修剪链表
127.0.0.1:6379> Rpush mylist "hello"
(integer) 1
127.0.0.1:6379> Rpush mylist "hello1"
(integer) 2
127.0.0.1:6379> Rpush mylist "hello2"
(integer) 3
127.0.0.1:6379> Rpush mylist "hello3"
(integer) 4
127.0.0.1:6379> Rpush mylist "hello4"
(integer) 5
127.0.0.1:6379> LRANGE mylist 0 -1
1) "hello"
2) "hello1"
3) "hello2"
4) "hello3"
5) "hello4"
127.0.0.1:6379> ltrim mylist 1 2 # 通过下标截取指定的长度,这个list已经被改变了,截断了只剩下截取的元素!
OK
127.0.0.1:6379> LRANGE mylist 0 -1
1) "hello1"
2) "hello2"
移除列表的最后一个元素到新的列表中
127.0.0.1:6379> Rpush mylist "hello" "hello1" "hello2" "hello3" "hello4"
(integer) 5
127.0.0.1:6379> LRANGE mylist 0 -1
1) "hello"
2) "hello1"
3) "hello2"
4) "hello3"
5) "hello4"
127.0.0.1:6379> rpoplpush mylist myotherlist # 移除列表的最后一个元素,将他移动到新的链表的最左边
"hello4"
127.0.0.1:6379> LRANGE mylist 0 -1 # 查看原来的列表
1) "hello"
2) "hello1"
3) "hello2"
4) "hello3"
127.0.0.1:6379> LRANGE myotherlist 0 -1 # 查看目标列表中,确实存在改值
1) "hello4"
插入到某个元素的前面或者后面
127.0.0.1:6379> Rpush mylist "hello"
(integer) 1
127.0.0.1:6379> Rpush mylist "world"
(integer) 2
127.0.0.1:6379> LRANGE mylist 0 -1
1) "hello"
2) "world"
127.0.0.1:6379> LINSERT mylist before "world" "other" # 把 other 插入到 world 的前面
(integer) 3
127.0.0.1:6379> LRANGE mylist 0 -1
1) "hello"
2) "other"
3) "world"
127.0.0.1:6379> LINSERT mylist after "world" "new" # 把 new插入到 world 的前面
(integer) 4
127.0.0.1:6379> LRANGE mylist 0 -1
1) "hello"
2) "other"
3) "world"
4) "new"
拓展
命令 | 说明 | 备注 |
---|---|---|
blpop key timeout | 移出并获取列表的第一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止 | 相对于 lpop 命令,它的操作是进程安全的 |
brpop key timeout | 移出并获取列表的最后一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止 | 相对于 rpop 命令,它的操作是进程安全的 |
rpoplpush key src dest | 按从左到右的顺序,将一个链表的最后一个元素移除,并插入目标链表的最左端 | 不能设置超时间 |
blpoplpush key src dest timeout | 按从左到右的顺序,将一个链表的最后一个元素移除,并插入目标链表的最左端,并可以设置超时时间 | 可以设置超时间 |
小结
如果key 不存在,创建新的链表
如果key存在,新增内容
如果移除了所有值,空链表,也代表不存在!
在两边插入或者改动值,效率最高! 中间元素,相对来说效率会低一点~
消息排队!消息队列 (Lpush Rpop), 栈( Lpush Lpop)!
Set(集合)
set中的值是不能重读的
集合的添加、查看、判断是否存在、元素个数
127.0.0.1:6379> sadd myset "hello" # set集合中添加元素
(integer) 1
127.0.0.1:6379> sadd myset "xiaoyequ"
(integer) 1
127.0.0.1:6379> sadd myset "love"
(integer) 1
127.0.0.1:6379> smembers myset # 查看指定set的所有值
1) "love"
2) "xiaoyequ"
3) "hello"
127.0.0.1:6379> sismember myset hello # 判断某一个值是不是在set集合中
(integer) 1
127.0.0.1:6379> sismembermyset world
(integer) 0
127.0.0.1:6379> scard myset # 获取set集合中的内容元素个数
(integer) 3
移除set集合中的指定元素
127.0.0.1:6379> scard myset # 移除set集合中的指定元素
(integer) 3
127.0.0.1:6379> srem myset hello
(integer) 1
127.0.0.1:6379> scard myset
(integer) 2
127.0.0.1:6379> smembers myset
1) "love"
2) "xiaoyequ"
随机抽选出一个元素
set 无序不重复集合,抽随机
127.0.0.1:6379> smembers myset
1) "love"
2) "xiaoyequ"
3) "hello"
127.0.0.1:6379> srandmember myset # 随机抽选出一个元素
"hello"
127.0.0.1:6379> srandmember myset
"xiaoyequ"
127.0.0.1:6379> srandmember myset
"love"
127.0.0.1:6379> srandmember myset 2 # 随机抽选出指定个数的元素
1) "love"
2) "hello"
127.0.0.1:6379> srandmember myset 2
1) "love"
2) "hello"
127.0.0.1:6379> srandmember myset 2
1) "xiaoyequ"
2) "hello"
随机删除key
127.0.0.1:6379> smembers myset
1) "love"
2) "xiaoyequ"
3) "hello"
127.0.0.1:6379> spop myset # 随机删除一些set集合中的元素
"xiaoyequ"
127.0.0.1:6379> spop myset
"love"
127.0.0.1:6379> smembers myset
1) "hello"
将一个指定的值,移动到另外一个set集合
127.0.0.1:6379> sadd myset "hello"
(integer) 1
127.0.0.1:6379> sadd myset "world"
(integer) 1
127.0.0.1:6379> sadd myset "xiaoyequ"
(integer) 1
127.0.0.1:6379> sadd myset2 "set2"
(integer) 1
127.0.0.1:6379> smove myset myset2 "xiaoyequ" # 将一个指定的值,移动到另外一个set集合
(integer) 1
127.0.0.1:6379> smembers myset
1) "world"
2) "hello"
127.0.0.1:6379> smembers myset2
1) "set2"
2) "xiaoyequ"
差集、交集、并集
微博,B站,共同关注!(并集)
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) "a"
2) "b"
127.0.0.1:6379> sinter key1 key2 # 交集 共同好友就可以这样实现
1) "c"
127.0.0.1:6379> sunion key1 key2 # 并集
1) "a"
2) "b"
3) "c"
4) "d"
5) "e"
127.0.0.1:6379> sdiffstore des1 key1 key2 # 差集(保存到des1)
(integer) 2
127.0.0.1:6379> sinterstore des2 key1 key2 # 交集(保存到des2)
(integer) 1
127.0.0.1:6379> sunionstore des3 key1 key2 # 并集(保存到des3)
(integer) 5
127.0.0.1:6379> smembers des1
1) "a"
2) "b"
127.0.0.1:6379> smembers des2
1) "c"
127.0.0.1:6379> smembers des3
1) "a"
2) "b"
3) "c"
4) "d"
5) "e"
应用场景
微博,A用户将所有关注的人放在一个set集合中!将它的粉丝也放在一个集合中!
共同关注,共同爱好,二度好友,推荐好友!
Hash(哈希)
Map集合,key-map 这个值是一个map集合! 本质和String类型没有太大区别,还是一个简单的 key-value
hash添加、获取、删除字段、判断是否存在
127.0.0.1:6379> hset myhash field1 xiaoyequ # set一个具体 key-value
(integer) 1
127.0.0.1:6379> hget myhash field1 # 获取一个字段值
"xiaoyequ"
127.0.0.1:6379> hmset myhash field1 hello field2 world # set多个 key-value(覆盖field1)
OK
127.0.0.1:6379> hmget myhash field1 field2 # 获取多个字段值
1) "hello"
2) "world"
127.0.0.1:6379> hgetall myhash # 获取全部数据
1) "field1"
2) "hello"
3) "field2"
4) "world"
127.0.0.1:6379> hdel myhash field1 # 删除hash指定key字段!对应的value值也就消失了
(integer) 1
127.0.0.1:6379> hgetall myhash
1) "field2"
2) "world"
127.0.0.1:6379> hexists myhash field1 # 判断hash中指定字段是否存在
(integer) 0
127.0.0.1:6379> hexists myhash field2
(integer) 1
只获得所有field / value
127.0.0.1:6379> hkeys myhash # 只获得所有field
1) "field2"
127.0.0.1:6379> hvals myhash # 只获得所有value
1) "world"
指定增量、条件赋值
127.0.0.1:6379> hset myhash field3 5
(integer) 1
127.0.0.1:6379> hincrby myhash field3 1 # 指定增量
(integer) 6
127.0.0.1:6379> hincrby myhash field3 -1
(integer) 5
127.0.0.1:6379> hsetnx myhash field4 hello # 如果不存在则可以设置
(integer) 1
127.0.0.1:6379> hsetnx myhash field4 world # 如果存在则不能设置
(integer) 0
应用场景
hash变更的数据 user name age,尤其是是用户信息之类的,经常变动的信息! hash 更适合于对象的存储,String更加适合字符串存储
Zset(有序集合)
在set的基础上,增加了一个 score 值
有序集合添加成员、查看成员、获取成员个数
127.0.0.1:6379> zadd myset 1 one # 添加一个成员
(integer) 1
127.0.0.1:6379> zadd myset 2 two 3 three # 添加多个成员
(integer) 2
127.0.0.1:6379> zrange myset 0 -1 # 获得所有成员
1) "one"
2) "two"
3) "three"
127.0.0.1:6379> zcard myset # 获取有序集合中的个数
(integer) 3
有序集合排序
127.0.0.1:6379> zadd salary 2500 xiaoming # 添加三个用户
(integer) 1
127.0.0.1:6379> zadd salary 3000 xiaogang
(integer) 1
127.0.0.1:6379> zadd salary 7000 xiaoyequ
(integer) 1
127.0.0.1:6379> zadd salary 500 xiaohong
(integer) 1
127.0.0.1:6379> zrangebyscore salary -inf +inf # 显示全部的用户 从小到大
1) "xiaohong"
2) "xiaoming"
3) "xiaogang"
4) "xiaoyequ"
127.0.0.1:6379> zrevrange salary 0 -1 # 从大到进行排序
1) "xiaoyequ"
2) "xiaogang"
3) "xiaoming"
4) "xiaohong"
127.0.0.1:6379> zrangebyscore salary -inf +inf withscores # 显示全部的用户并且附带成绩
1) "xiaohong"
2) "500"
3) "xiaoming"
4) "2500"
5) "xiaogang"
6) "3000"
7) "xiaoyequ"
8) "7000"
127.0.0.1:6379> zrangebyscore salary -inf 3500 withscores # 显示工资小于3500员工的升序排序
1) "xiaohong"
2) "500"
3) "xiaoming"
4) "2500"
5) "xiaogang"
6) "3000"
移除成员
127.0.0.1:6379> zrange salary 0 -1
1) "xiaohong"
2) "xiaoming"
3) "xiaogang"
4) "xiaoyequ"
127.0.0.1:6379> zrem salary xiaohong # 移除有序集合中的指定元素
(integer) 1
127.0.0.1:6379> zrange salary 0 -1
1) "xiaoming"
2) "xiaogang"
3) "xiaoyequ"
获取指定区间(score)的成员数量
127.0.0.1:6379> zcount salary 300 4000 # 获取指定区间的成员数量
(integer) 2
127.0.0.1:6379> zcount salary 300 2700
(integer) 1
应用场景
set 排序 存储班级成绩表,工资表排序
普通消息,1、重要消息 2、带权重进行判断
排行榜应用实现,取Top N 测试
三种特殊类型数据
geospatial地理位置
geospatial地理位置:朋友的定位,附近的人,打车距离计算?
测试数据:www.jsons.cn/lngcode/
这个功能可以推算地理位置的信息.两地之间的距离,方圆几里的人
添加、获取地理位置
南极、北极无法添加,我们一般会下载城市数据,直核通过java程序一 次性导入
参数:geoadd key 值(经度,纬度,名称)
geopos key 值(名称)
127.0.0.1:6379> geoadd china:city 116.440 39.90 beijing # 添加地理位置
(integer) 1
127.0.0.1:6379> geoadd china:city 121.47 31.23 shanghai
(integer) 1
127.0.0.1:6379> geoadd china:city 106.50 29.53 chongqing 114.05 22.52 shenzhen
(integer) 2
127.0.0.1:6379> geoadd china:city 120.16 30.24 hangzhou 108.96 34.26 xian
(integer) 2
127.0.0.1:6379> geopos china:city beijing # 获取地理位置
1) 1) "116.44000142812728882"
2) "39.90000009167092543"
127.0.0.1:6379> geopos china:city beijing chongqing
1) 1) "116.44000142812728882"
2) "39.90000009167092543"
2) 1) "106.49999767541885376"
2) "29.52999957900659211"
返回两坐标的距离
单位:
- m:表示单位为米。
- km:表示单位为千米。
- mi:表示单位为英里。
- ft:表示单位为英尺。
127.0.0.1:6379> geodist china:city beijing shanghai km # 北京到上海的直线距离
"1065.8365"
以给定的经纬度为中心,找出给定距离的元素
- withdist:查询出带有距离
- withcoord:查询出带有经纬度
- count 3:限制显示 3 个
127.0.0.1:6379> georadius china:city 110 30 500 km # 获取经度110纬度30为中心,方圆500km的城市
1) "chongqing"
2) "xian"
127.0.0.1:6379> georadius china:city 110 30 1000 km
1) "chongqing"
2) "xian"
3) "shenzhen"
4) "hangzhou"
127.0.0.1:6379> georadius china:city 110 30 1000 km withdist # 查询出带有距离
1) 1) "chongqing"
2) "341.9374"
2) 1) "xian"
2) "483.8340"
3) 1) "shenzhen"
2) "924.6408"
4) 1) "hangzhou"
2) "977.5143"
127.0.0.1:6379> georadius china:city 110 30 1000 km withcoord # 查询出带有经纬度
1) 1) "chongqing"
2) 1) "106.49999767541885376"
2) "29.52999957900659211"
2) 1) "xian"
2) 1) "108.96000176668167114"
2) "34.25999964418929977"
3) 1) "shenzhen"
2) 1) "114.04999762773513794"
2) "22.5200000879503861"
4) 1) "hangzhou"
2) 1) "120.1600000262260437"
2) "30.2400003229490224"
127.0.0.1:6379> georadius china:city 110 30 1000 km count 3 # 限制显示 3 个
1) "chongqing"
2) "xian"
3) "shenzhen"
以给定的已存的位置为中心,找出给定距离的元素
127.0.0.1:6379> georadiusbymember china:city beijing 1000 km # 获取以北京为中心,方圆1000km的城市
1) "beijing"
2) "xian"
127.0.0.1:6379> georadiusbymember china:city beijing 1200 km
1) "beijing"
2) "hangzhou"
3) "shanghai"
4) "xian"
127.0.0.1:6379> georadiusbymember china:city beijing 1500 km
1) "chongqing"
2) "xian"
3) "hangzhou"
4) "shanghai"
5) "beijing"
返回一个或多个位置元素的hash
将二维的经纬度转换为一维的字符串
127.0.0.1:6379> geohash china:city beijing # 获取beijing位置的hash值
1) "wx4fcxt42e0"
127.0.0.1:6379> geohash china:city beijing shanghai
1) "wx4fcxt42e0"
2) "wtw3sj5zbj0"
GEO底层其实就是Zset
我们可以使用Zset命令来操作geo
127.0.0.1:6379> zrange china:city 0 -1 # 获取所有位置
1) "chongqing"
2) "xian"
3) "shenzhen"
4) "hangzhou"
5) "shanghai"
6) "beijing"
127.0.0.1:6379> zrem china:city chongqing # 删除重庆的位置
(integer) 1
127.0.0.1:6379> zrange china:city 0 -1
1) "xian"
2) "shenzhen"
3) "hangzhou"
4) "shanghai"
5) "beijing"
Hyperloglog基数统计
Redis Hyperlogog:基数统计的算法
优点:占用的内存是固定,2^64不同的元素的技术,只需要12KB内存~
网页的UV (一个人访问一个网站多次,但是还是算作一个人 )
传统的方式,set 保存用户的id,然后就可以统计set中的元素数量作为标准判断
这个方式如果保存大量的用户id,就会比较麻烦,我们的目的是为了计数,而不是保存用户id
0.81%错误率!统计UV任务,可以忽略不计的!
测试使用
127.0.0.1:6379> pfadd mykey a b c d e f g h i j # 创建第一组元素mykey
(integer) 1
127.0.0.1:6379> pfcount mykey # 统计mykey 元素的基数数量
(integer) 10
127.0.0.1:6379> pfadd mykey2 i j z x c v b n m # 创建第二组元素mykey
(integer) 1
127.0.0.1:6379> pfcount mykey2
(integer) 9
127.0.0.1:6379> pfmerge mykey3 mykey mykey2 # 合并两组mykey mykey2 => mykey3 并集
OK
127.0.0.1:6379> pfcount mykey3 # 查看并集的数量
(integer) 15
Bitmaps 用二进制记录
统计用户信息,活跃,不活跃,登录、未登录,打卡。365天打卡。两个状态的,都可以使用Bitmaps
Bitmaps位图,数据结构,都是操作二进制位来进行记录,就只有0和1两个状态
测试使用
使用bitmaps来记录周一到周日的打卡
127.0.0.1:6379> setbit sign 0 1 # 周一打卡
(integer) 0
127.0.0.1:6379> setbit sign 1 0 # 周二未打卡
(integer) 0
127.0.0.1:6379> setbit sign 2 0 # 周三未打卡
(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 0 # 周六未打卡
(integer) 0
127.0.0.1:6379> setbit sign 6 0 # 周日未打卡
(integer) 0
127.0.0.1:6379> getbit sign 3 # 获取周四打卡情况
(integer) 1
127.0.0.1:6379> getbit sign 6 # 获取周日打卡情况
(integer) 0
127.0.0.1:6379> bitcount sign # 统计打卡天数
(integer) 3