简介-来自官网
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)。
基本命令
#切换数据库
select 3
#查看DB大小 没有存数据的时候是0
dbsize
#查看当前数据库所有的key
keys *
#清空当前库
flushdb
#清空所有的数据库
flushall
#查看库中是否存在某个键
exists key
#删除某个键值 1代表当前库
move key 1
#设置某个键多少秒过期
expire key 10
#查看还剩多长时间过期
ttl key
#查看当前key的类型
type key
五大基本数据类型
1.String类型
#往字符串后追加字符串,返回的是字符串的长度,如果key不存在相当于新建
append key “asd”
#获取字符串的长度
strlen key
++ – 操作
#值加1
incr key
#值减1
decr key
#加减指定值(步长)
incrby key 10
decrby key 10
字符串的截取
#截取0-3的字符串
getrange key 0 3
#返回字符串
getrange key 0 -1
#替换指定位置开始的字符串
setrange key 1 xiaoming
#设置过期时间
setex(set with expire)
#不存在再设置
setnx (set if not exist)
#设置key的值为hello 30 秒后过期
setex key 30 “hello”
#如果不存在创建key 如果存在创建失败 返回0表示创建失败返回1表示创建成功
setnx key “redis”
#一次性设置多个值
mset k1 v1 k2 v2
#一次性获取多个
mget K1 K2
#如果不存在再创建,以下不会创建成功 因为msetnx是原子操作
msetnx k1 v1 k3 v3
设置对象
#设置一个usr:1对象值为一个json格式。格式为usr:{id}:{filed}
set usr:1 {name:zhangsan,age:3}
#mset设置
mset usr:1:name zhangsan user:1:age 3
#mget获取
mget usr:1:name usr:1:age
#如果不存在则返回null,并设置新值。如果存在值获取原来的值并设置新值
getset key value
#可以获取到value
get key
2.list类型
所有的list都是以l开头,redis命令不区分大小写
lpush:头部插入 rpush:尾部插入 lrange:获取集合中的值
#将一个值或者多个值插入列表的头部
127.0.0.1:6379[2]> lpush list one
(integer) 1
127.0.0.1:6379[2]> lpush list two
(integer) 2
127.0.0.1:6379[2]> lpush list three
(integer) 3
#获取list中的值
127.0.0.1:6379[2]> lrange list 0 -1
1) "three"
2) "two"
3) "one"
127.0.0.1:6379[2]> lrange list 0 1
1) "three"
2) "two"
#将一个或多个值插入列表尾部
127.0.0.1:6379[2]> rpush list right
(integer) 4
127.0.0.1:6379[2]> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "right"
rpop:移除list的最后一个元素,lpop: 移除list的第一个元素
127.0.0.1:6379[2]> lrange list 0 -1
1) "three"
2) "two"
3) "one"
#移除第一个元素,返回移除的元素
127.0.0.1:6379[2]> lpop list
"three"
#移除最后一个元素,返回移除的元素
127.0.0.1:6379[2]> rpop list
"one"
127.0.0.1:6379[2]> lrange list 0 -1
1) "two"
lindex:通过下标获取list中的某一个值
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "ont"
#通过下标获取list中的某一个值
127.0.0.1:6379> lindex list 1
"two"
#llen返回list的长度
127.0.0.1:6379> llen list
(integer) 3
lrem:移除list集合中指定的value
#删除一个ont 精确删除
127.0.0.1:6379> lrem list 1 ont
(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
#删除两个three
127.0.0.1:6379> lrem list 2 three
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "two"
trim:修剪,截断
127.0.0.1:6379> lpush list hello2 hello3 hello4
(integer) 5
127.0.0.1:6379> lrange list 0 -1
1) "hello4"
2) "hello3"
3) "hello2"
4) "hello"
5) "two"
#通过下标截取指定的长度,这个list已经改变了
127.0.0.1:6379> ltrim list 1 2
OK
#截断后只剩下截取的元素
127.0.0.1:6379> lrange list 0 -1
1) "hello3"
2) "hello2"
rpoplpush:移除列表的最后一个元素,将他移动到新的列表中
127.0.0.1:6379> lrange list 0 -1
1) "hello3"
2) "hello2"
3) "hello1"
#移除列表的最后一个元素,将他移动到新的列表中
127.0.0.1:6379> rpoplpush list mylist
"hello1"
#原来的list集合
127.0.0.1:6379> lrange list 0 -1
1) "hello3"
2) "hello2"
#查看新的mylist集合
127.0.0.1:6379> lrange mylist 0 -1
1) "hello1"
127.0.0.1:6379>
lset:将列表中指定下标的值替换为另一个值,更新操作
#判断集合是否存在
127.0.0.1:6379> exists list1
(integer) 0
#不存在我们更新会报错
127.0.0.1:6379> lset list1 0 word
(error) ERR no such key
#在集合中加一个元素
127.0.0.1:6379> lpush list1 hello
(integer) 1
#更新当前下标的值
127.0.0.1:6379> lset list1 0 world
OK
#更新成功
127.0.0.1:6379> lrange list1 0 -1
1) "world"
#越界更新
127.0.0.1:6379> lset list1 1 other
(error) ERR index out of range
linsert:将某个具体的value插入到指定元素的前面或后面
127.0.0.1:6379> lrange list 0 -1
1) "hello3"
2) "hello2"
#前面插值
127.0.0.1:6379> linsert list before hello2 123
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "hello3"
2) "123"
3) "hello2"
#后面插值
127.0.0.1:6379> linsert list after 123 456
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "hello3"
2) "123"
3) "456"
4) "hello2"
list总结:
它实际上是一个链表,类似before node after left node right 都可以插入
key如果不存在创建新的链表
如果key存在则新增内容
两边插值或者改动效率最高,中间改动元素效率会低
3.set集合
无序不重复集合
sadd:集合添加 smembers:查看集合元素,sismember 判断元素是否在集合中,scard 获取元素个数
#set集合中添加元素
127.0.0.1:6379> sadd myset hello
(integer) 1
127.0.0.1:6379> sadd myset hello1
(integer) 1
127.0.0.1:6379> sadd myset hello2
(integer) 1
#查看set集合的值
127.0.0.1:6379> smembers myset
1) "hello1"
2) "hello2"
3) "hello"
#判断某个元素是不是在set集合中
127.0.0.1:6379> sismember myset hello
(integer) 1
#查看set集合中元素的个数
127.0.0.1:6379> scard myset
(integer) 3
srem:删除集合中指定元素
#删除集合中指定元素
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) "hello1"
2) "hello2"
srandmember:随机抽取元素
#随机插入一个元素
127.0.0.1:6379> sadd myset world
(integer) 1
127.0.0.1:6379> smembers myset
1) "hello1"
2) "hello"
3) "hello2"
4) "world"
#随机抽取一个元素
127.0.0.1:6379> srandmember myset
"hello1"
# 随机抽取两个元素
127.0.0.1:6379> srandmember myset 2
1) "hello1"
2) "hello"
spop :随机删除set集合中的一个元素
127.0.0.1:6379> smembers myset
1) "hello1"
2) "hello"
3) "hello2"
4) "world"
#随机删除set集合中的一个元素,返回删除的元素
127.0.0.1:6379> spop myset
"world"
smove:将一个指定的值移动到另一个set集合中
#查看set集合中的元素
127.0.0.1:6379> smembers myset
1) "hello1"
2) "hello"
3) "hello2"
#将myset集合中的hello元素移到myset1集合中
127.0.0.1:6379> smove myset myset1 hello
(integer) 1
127.0.0.1:6379> smembers myset
1) "hello1"
2) "hello2"
127.0.0.1:6379> smembers myset1
1) "hello"
差集 sdiff交集sinter并集sunion
#新建set1
127.0.0.1:6379> sadd set1 a b c d
(integer) 4
#新建set2
127.0.0.1:6379> sadd set2 a c e f
(integer) 4
#差集
127.0.0.1:6379> sdiff set1 set2
1) "b"
2) "d"
#交集 共同好友可以这么实现
127.0.0.1:6379> sinter set1 set2
1) "c"
2) "a"
#并集
127.0.0.1:6379> sunion set1 set2
1) "f"
2) "e"
3) "a"
4) "d"
5) "c"
6) "b"
127.0.0.1:6379>
4.hash(哈希) key –map集合
#set一个具体的key -value
127.0.0.1:6379> hset myhash key1 hello
(integer) 1
#获取一个键的值
127.0.0.1:6379> hget myhash key1
"hello"
#set多个key-value
127.0.0.1:6379> hmset myhash key2 world key3 hash
OK
#获取多个字段值
127.0.0.1:6379> hmget myhash key2 key3
1) "world"
2) "hash"
# 获取全部的数据
127.0.0.1:6379> hgetall myhash
1) "key1"
2) "hello"
3) "key2"
4) "world"
5) "key3"
6) "hash"
#删除指定的key 对应的值也将删除
127.0.0.1:6379> hdel myhash key1
(integer) 1
#获取key-value的数量
127.0.0.1:6379> hlen myhash
(integer) 2
#判断hash中指定字段是否存在
127.0.0.1:6379> hexists myhash key2
(integer) 1
#获得所有的key
127.0.0.1:6379> hkeys myhash
1) "key2"
2) "key3"
#获得所有的值
127.0.0.1:6379> hvals myhash
1) "world"
2) "hash"
incr :增加值decr:减少值
#指定增量
127.0.0.1:6379> hincrby myhash key4 5
(integer) 11
#获取所有数据
127.0.0.1:6379> hgetall myhash
1) "key2"
2) "world"
3) "key3"
4) "hash"
5) "key4"
6) "11"
127.0.0.1:6379> hincrby myhash key4 -2
(integer) 9
#如果不存在可以设置
127.0.0.1:6379> hsetnx myhash key5 hello
(integer) 1
# 如果存在不能设置
127.0.0.1:6379> hsetnx myhash key5 word
(integer) 0
hash适合存放经常变动的信息。hash更适合于对象的存储,string适合字符串的存储
5.zset有序集合
#添加一个值
127.0.0.1:6379> zadd myzset 1 one
(integer) 1
#添加两个值
127.0.0.1:6379> zadd myzset 2 two 3 three
(integer) 2
#查看值
127.0.0.1:6379> zrange myzset 0 -1
1) "one"
2) "two"
3) "three"
127.0.0.1:6379>
排序
#添加三组数据
127.0.0.1:6379> zadd salary 300 a1
(integer) 1
127.0.0.1:6379> zadd salary 400 a2
(integer) 1
127.0.0.1:6379> zadd salary 500 a3
(integer) 1
#显示全部按从小到大的顺序
127.0.0.1:6379> zrangebyscore salary -inf +inf
1) "a1"
2) "a2"
3) "a3"
#从大到小
127.0.0.1:6379> zrevrange salary 0 -1
1) "a3"
2) "a2"
#显示全部数据并带有工资金额
127.0.0.1:6379> zrangebyscore salary -inf +inf withscores
1) "a1"
2) "300"
3) "a2"
4) "400"
5) "a3"
6) "500"
#显示工资小于400的员工升序排列
127.0.0.1:6379> zrangebyscore salary -inf 400 withscores
1) "a1"
2) "300"
3) "a2"
4) "400"
#移除有序集合中的指定元素
127.0.0.1:6379> zrem salary a1
(integer) 1
127.0.0.1:6379> zrange salary 0 -1
1) "a2"
2) "a3"
#获取个数
127.0.0.1:6379> zcard salary
(integer) 2
# 查看元素个数
127.0.0.1:6379> zcount myzset -inf +inf
#查看区间元素个数
127.0.0.1:6379> zcount myset 1 3
(integer) 3
三种特殊的数据类型
1.geo
geospatial地理位置,应用场景:附近的人,定位 ,距离计算
geoadd 添加地理位置
规则:两级无法直接添加,我们一般会下载一些城市的数据,使用java程序一次性导入
参数keyd的值(纬度 经度 名称)
经纬度查询网站:https://jingweidu.51240.com
有效经度在-180 到180
有效纬度在-85.05 85.05 超出范围会报错
# 添加城市的经纬度和城市名
127.0.0.1:6379[2]> geoadd china:city 116.39 39.80 beijing
(integer) 1
127.0.0.1:6379[2]> geoadd china:city 121.40 31.59 shanghai
(integer) 1
#插入多个
127.0.0.1:6379[2]> geoadd china:city 120.12 30.16 hangzhou 117.29 39.70 tianjin
(integer) 2
#获取对应城市的经纬度
127.0.0.1:6379[2]> geopos china:city shanghai
1) 1) "121.40000134706497"
2) "31.590000416576423"
# 获取多个
127.0.0.1:6379[2]> geopos china:city tianjin hangzhou
1) 1) "117.28999882936478"
2) "39.700000453314438"
2) 1) "120.11999756097794"
2) "30.159999453717965"
geodist两人之间的距离
单位 m km ml (英里)ft(英尺)
#上海到北京的直线距离 默认是m
127.0.0.1:6379[2]> geodist china:city shanghai beijing
"1018697.6191"
#km表示
127.0.0.1:6379[2]> geodist china:city shanghai beijing km
"1018.6976"
georadius
以某一经纬度为中心,找出某一半径内的元素
应用场景:附近的人(获得所有附近人得地址,定位)通过半径查询
获得指定数量的人 200
所有数据都应录入china:city才会让结果更加清楚
#指定位置为中心,查找1000km以内的城市
127.0.0.1:6379[2]> georadius china:city 116 39 200 km
1) "beijing"
2) "tianjin"
#显示经纬度
127.0.0.1:6379[2]> georadius china:city 116 39 200 km withcoord
1) 1) "beijing"
2) 1) "116.38999968767166"
2) "39.800000272492674"
2) 1) "tianjin"
2) 1) "117.28999882936478"
2) "39.700000453314438"
#显示距离
127.0.0.1:6379[2]> georadius china:city 116 39 200 km withdist
1) 1) "beijing"
2) "95.0850"
2) 1) "tianjin"
2) "135.5425"
#显示经纬度和距离
127.0.0.1:6379[2]> georadius china:city 116 39 200 km withdist withcoord
1) 1) "beijing"
2) "95.0850"
3) 1) "116.38999968767166"
2) "39.800000272492674"
2) 1) "tianjin"
2) "135.5425"
3) 1) "117.28999882936478"
2) "39.700000453314438"
#限制显示一个
127.0.0.1:6379[2]> georadius china:city 116 39 200 km withdist withcoord count 1
1) 1) "beijing"
2) "95.0850"
3) 1) "116.38999968767166"
2) "39.800000272492674"
#找出指定元素周围的其他元素
127.0.0.1:6379[2]> georadiusbymember china:city beijing 500 km
1) "beijing"
2) "tianjin"
geohash
返回一个或多个位置元素的geohash表示
该命令将返回一个11位的geohash字符串
将二维的经纬度转化为一个字符串,两个字符串越接近,则距离越近
127.0.0.1:6379[2]> geohash china:city beijing tianjin
1) "wx4f2t2eg90"
2) "wx53ugpvr00"
geo的底层使用的就说zset我们可以使用zset命令来操作geo
127.0.0.1:6379[2]> zrange china:city 0 -1
1) "hangzhou"
2) "shanghai"
3) "beijing"
4) "tianjin"
127.0.0.1:6379[2]> zrem china:city beijing
(integer) 1
2.hyperloglog
redis2.8.9以后开始使用hyperloglog
redis Hyper log log基数统计算法、
优点:占用的内存是固定的2^64个不同的元素的基数,只需要12kb的内存
网页的UV(一个人访问一个网站多次,但是还算是一个人)
传统的方式,set保存用户的id ,然后就可以统计set中的元素的数量作为判断的标准
这个方式如果保存大量的用户id,就会比较麻烦,我们的目的是计数,而不是存储用户id
允许有0.81%的错误率,对于统计UV任务,可以忽略不记
#新建第一组元素mykey
127.0.0.1:6379[2]> pfadd mykey a b c d e f g h i j
(integer) 1
#统计mykey基数的数量
127.0.0.1:6379[2]> pfcount mykey
(integer) 10
#创建第二组元素mykey2
127.0.0.1:6379[2]> pfadd mykey2 i j a b c m k l
(integer) 1
#第二组基数的数量
127.0.0.1:6379[2]> pfcount mykey2
(integer) 8
#合并两组放到mykey3中 并集
127.0.0.1:6379[2]> pfmerge mykey3 mykey mykey2
OK
#查看并集数量
127.0.0.1:6379[2]> pfcount mykey3
(integer) 13
如果允许容错 那么一定可以使用htyperloglog
如果不允许可以使用set
bitmaps位存储
统计用户信息,活跃不活跃!登录未登录!打卡,两个状态的都可以使用bitmaps
bitmaps位图,使用数据结构,通过操作二进制位来进行记录只有0和1两个状态
使用bitmaps记录周一到周日的打卡
#插入数据
127.0.0.1:6379[2]> setbit sign 0 1
(integer) 0
127.0.0.1:6379[2]> setbit sign 1 0
(integer) 0
127.0.0.1:6379[2]> setbit sign 2 1
(integer) 0
127.0.0.1:6379[2]> setbit sign 3 0
(integer) 0
#set 除0和1的数据会报错
127.0.0.1:6379[2]> setbit sign 4 4
(error) ERR bit is not an integer or out of range
127.0.0.1:6379[2]> setbit sign 4 1
(integer) 0
127.0.0.1:6379[2]> setbit sign 5 1
(integer) 0
127.0.0.1:6379[2]> setbit sign 6 1
(integer) 0
#获取某天是否打卡
127.0.0.1:6379[2]> getbit sign 3
(integer) 0
127.0.0.1:6379[2]> getbit sign 6
(integer) 1
#查看总打卡记录
127.0.0.1:6379[2]> bitcount sign
(integer) 5
redis官网
redis中文网