REDIS使用
连接redis
# 安装redis-cli
sudo apt-get install redis-tools
# 连接redis, redis-cli -h ip -p 端口号 -a 密码
redis-cli -h 127.0.0.1 -p 65500 -a root
简单redis命令
# 查看所有key
keys *
# 创建/更新一个key
set name zhouheng
# 删除一个key
del name
# 删除当前数据库
flushdb
# 删除所有数据库
flushall
# 查看某个key是否存在
exists name
# 数据迁移, 将name迁移到 1 这个数据库
move name 1
# 数据库切换, 切换到数据库 1
select 1
# 设置数据 过期时间, 5秒
expire name 5
# 查看一个key的剩余生存时间
ttl name
# 查看一个key的类型
type name
# 清屏
clear
String类型
# 设置值
127.0.0.1:65500> set key1 "hello world"
OK
# 同时设置多个值
127.0.0.1:65500> keys *
(empty list or set)
127.0.0.1:65500> mset k1 v1 k2 v2 k3 v3
OK
127.0.0.1:65500> keys *
1) "k1"
2) "k3"
3) "k2"
127.0.0.1:65500> mset k1 newv1 k4 v4
OK
127.0.0.1:65500> keys *
1) "k1"
2) "k3"
3) "k4"
4) "k2"
127.0.0.1:65500> get k1
"newv1"
# 查看值
127.0.0.1:65500> get key1
"hello world"
# 同时查看多个值
127.0.0.1:65500> mget k1 k2 k3
1) "newv1"
2) "v2"
3) "v3"
# 不存在才设置
127.0.0.1:65500> set key1 "hello world"
OK
127.0.0.1:65500> get key1
"hello world"
127.0.0.1:65500> setnx key1 hw
(integer) 0
127.0.0.1:65500> get key1
"hello world"
127.0.0.1:65500> setnx key2 hw
(integer) 1
127.0.0.1:65500> get key2
"hw"
# 同时设置多个值, 不存在才设置, 原子操作
127.0.0.1:65500> keys *
1) "k1"
2) "k3"
3) "k4"
4) "k2"
127.0.0.1:65500> msetnx k2 newv2 k5 v5
(integer) 0
127.0.0.1:65500> keys *
1) "k1"
2) "k3"
3) "k4"
4) "k2"
# 设置过期时间, 同时设置值, 原子性操作
127.0.0.1:65500> setex key1 10 hello
OK
127.0.0.1:65500> ttl key1
(integer) 5
127.0.0.1:65500> get key1
"hello"
127.0.0.1:65500> get key1
(nil)
# 追加值, 如果key不存在 相当于 set
append key1 "hello"
# 获取字符串长度
strlen key1
自增 自减
# 自增, 如果key不存在, 从0开始, 自增后的结果是 1
incr views
# 自减, 如果key不存在, 从0开始, 自减后的结果是 -1
decr views
# 指定步长自增, 如果key不存在, 从0开始
incrby views 3
# 指定步长自减, 如果key不存在, 从0开始
decrby views 3
截取
# 截取字符串, 索引从0开始, 左右都是闭区间
127.0.0.1:65500> set key1 "hello world"
OK
127.0.0.1:65500> get key1
"hello world"
127.0.0.1:65500> getrange key1 0 4
"hello"
# 负索引截取字符串, 左右都是闭区间
127.0.0.1:65500> set key1 "hello world"
OK
127.0.0.1:65500> get key1
"hello world"
127.0.0.1:65500> getrange key1 -5 -1
"world"
替换
# 根据索引替换
127.0.0.1:65500> set key1 hello
OK
127.0.0.1:65500> get key1
"hello"
127.0.0.1:65500> setrange key1 2 66
(integer) 5
127.0.0.1:65500> get key1
"he66o"
对象
# 设置对象
127.0.0.1:65500> set user:1 {name:zhangsan,age:20}
OK
# 查看对象
127.0.0.1:65500> get user:1
"{name:zhangsan,age:20}"
# 分开设置
127.0.0.1:65500> mset user:1:name lisi user:1:age 3
OK
127.0.0.1:65500> get user:1
"{name:zhangsan,age:20}"
127.0.0.1:65500> mget user:1:name user:1:age
1) "lisi"
2) "3"
getset
# 先get 再set
127.0.0.1:65500> getset db redis
(nil)
127.0.0.1:65500> get db
"redis"
127.0.0.1:65500> getset db mongodb
"redis"
127.0.0.1:65500> get db
"mongodb"
List类型
在redis中 可以把list用作栈 队列 阻塞队列
list命令以 l 开头, 一般代表 队列左侧执行, r 代表队列右侧执行
# 将一个值或者多个值,插入到列表的头部(左)
lpush list one
lpush list two
lpush list three
# 查看全部元素
lrange list 0 -1
# 右插
rpush list four
弹出 pop
# 查看全部元素
lrange list 0 -1
# 左弹出list的第一个元素
lpop list
lrange list 0 -1
# 右弹出list的第一个元素
rpop list
索引 Index
lrange list 0 -1
# 通过下标获取list中的某一个值
lindex list 1
lrange list 0 -1
长度 llen
# 查看列表长度
llen list
移除指定的值 lrem
# 移除list中指定个数的value,精确匹配
lrem list 1 world
lrange list 0 -1
lrem list 2 hjk
lrange list 0 -1
截断 ltrim
lrange list 0 -1
# 通过下标截取指定长度,这个list已经被破坏了,截断之后只剩下截断后的元素
ltrim list 1 2
lrange list 0 -1
移除列表的最后一个元素,将他移动到新的列表中
lrange list 0 -1
rpoplpush list otherlist
lrange list 0 -1
lrange other 0 -1
将列表中指定下标的值替换为另一个值,更新操作 lset
# 判断这个列表是否存在
exists list
# 如果不存在,更新会报错
lset list 0 item
将某个具体的value插入到列表的中某个元素的前面或者后面 linsert
lrange list 0 -1
linsert list before "hello2" hello
lrange list 0 -1
linsert list after "hello2" hello
lrange list 0 -1
- list实际上是一个链表,前后都可以插入
- 如果key不存在,创建新的链表
- 如果移除了所有值,空链表,也代表不存在
- 在两边插入或者改动值,效率最高
Set 类型
# 在集合中添加元素
sadd myset "hello"
# 查看指定集合的所有值
smembers myset
# 判断某一个值是否在集合中
sismember myset hello
# 获取集合中值的个数
scard myset
# 移除元素
srem myset hello
# 随机抽取一个元素
srandmember myset
# 随机抽取指定个数的元素
srandmember myset 2
# 随机移除一个元素
spop myset
# 将一个特定的值,移动到另一个集合中
smove myset myset2 "kkk"
# 差集
sdiff key1 key2
# 交集
sinter key1 key2
# 并集
sunion key1 key2
Hash 类型
也是key-value形式,但是value是一个map
# set一个key-value
hset myhash field xxx
# 获取一个字段值
hget myhash field
# set多个key-value
hmset myhash field hello field world
# 获取全部的数据
hgetall myhash
# 删除指定的key,对应的value也就没有了
hdel myhash field
hgetall myhash
# 获取长度
hlen myhash
# 判断指定key是否存在
hexists myhash field1
# 获取所有的key
hkeys myhash
# 获取所有的value
hvals myhash
hset myhash field 5
# 指定增量
hincrby myhash field 1
hincrby muhash field -1
# 如果不存在可以设置
hsetnx myhash field hello
# 如果存在则不能设置
hsetnx myhash field world
Hash适合存储经常变动的对象信息,String更适合存储字符串
Zset 类型
# 添加一个值
zadd myset 1 one
# 添加多个值
zadd myset 2 two 3 three
zrange myset 0 -1
实现排序
zadd salary 2500 xiaohong
zadd salary 5000 xiaoming
zadd salary 500 xiaozhang
# 从小到大排序
zrange salary 0 -1
zrangebyscore salary -inf +inf
# 携带score一起展示
zrange salary 0 -1 WITHSCORES
# 从大到小排
zrevrange salary 0 -1 WITHSCORES
# 显示工资小于2500的用户
zrangebyscore salary -inf 2500 withscores
# 移除特定元素
zrem salary xiaohong
# 获取有序集合元素的个数
zcard salary
# 获取指定区间的人员数量
zcount myset 1 3
Geospatial
redis在3.2推出Geo类型,该功能可以推算出地理位置信息,两地之间的距离
文档:https://www.redis.net.cn/order/3687.html
借助网站模拟一些数据:百度搜经纬度查询即可
geoadd 添加地理位置
规则:两极无法直接添加,一般会下载城市数据,直接通过java程序一次性导入
有效的经度从-180度到180度。有效的纬度从-85.05112878度到85.05112878度。当坐标位置超出指定范围时,该命令会返回一个错误
添加一些模拟数据:
geoadd china:city 116.40 39.90 beijing
geoadd china:city 121.47 31.23 shanghai
geoadd china:city 106.50 29.53 chongqing 114.05 22.52 shenzhen
geoadd china:city 120.16 30.24 hanzghou 108.96 34.26 xian
# 获得指定城市的经纬度
geopos china:city beijng
geopos china:city shanghai
geodist 获取两个位置之间的距离
单位:
- m 表示单位为米
- km 表示单位为千米
- mi 表示单位为英里
- ft 表示单位为英尺
如果用户没有显式指定单位参数,默认使用米作为单位
# 查看北京和上海之间直接的直线距离
geodist china:city beijing shanghai km
georedius 以给定的经纬度为中心,找出某一半径内的元素
# 以110,30这个点为中心,找到方圆1000km的城市
georedius china:city 110 30 1000 km
# 显示他人的定位信息
georedius china:city 110 30 500 km withcoord
# 显示到中心点的距离
georedius china:city 110 30 500 km withdist
# 指定数量
georedius china:city 110 20 500 km whithcoord count 1
georediusmember 找出位于指定元素周围的其他元素
georediusmember china:city shanghai 1000 km
geo底层实现原理其实就是zset,可以使用zset命令操作geo
zrange china:city 0 -1
# 删除一个元素
zrem china:city beijing
zrange china:city 0 -1
Hyperloglog
基数:数学上集合的元素的个数,是不能重复的
UV(Unique visitor):是指通过互联网访问、浏览这个网页的自然人。访问的一个电脑客户端为一个访客,一天内同一个访客仅被计算一次。
redis 2.8.9 版本更新了hyperloglog 数据结构,是基于基数统计的算法。
hyperloglog 的优点是内存占用小,并且是固定的。存储2^64个不同元素的基数,只需要12KB的空间。但是也可能有 0.81% 的错误率。
这个数据结构常用于统计网站的UV。传统的方式是使用set保存用户的ID,然后统计set中元素的数量作为判断标准。但是这种方式保存了大量的用户ID,ID一般比较长,占空间,还很麻烦。我们的目的是计数,不是保存数据,所以这样做有弊端。但是如果使用hyperloglog 就比较合适了。
# 创建第一组元素
pfadd mykey a b c d e f g h i j
# 统计mykey基数
PFCOUNT mykey
# 创建第二组元素
pfadd mykey2 i j z x c v b n m
# 统计 mykey2基数
PFCOUNT mykey2
# 合并两组 mykey mykey2 => mykey3
PFMERGE mykey3 mykey mykey2
PFCOUNT mykey3
Bitmap
bitmap就是通过最小的单位bit来进行0或者1的设置,表示某个元素对应的值或者状态。一个bit的值,或者是0或者是1;也就是说一个bit能存储的最多信息是2
bitmap常用于统计用户信息 比如活跃粉丝和不活跃粉丝、登录和未登录、是否打卡等
这里使用一周打卡的案例说明其用法
# 周一打卡了
setbit sign 0 1
# 周二未打卡
setbit sign 1 0
# 周三未打卡
setbit sign 2 0
setbit sign 3 1
setbit sign 4 1
setbit sign 5 1
setbit sign 6 0
# 查看某一天是否打卡
GETBIT sign 3
GETBIT sign 6
# 统计打卡的天数
BITCOUNT sign