五大数据类型
官方文档:
翻译:
Redis 是一个开源(BSD 许可)内存数据结构存储系统,用作数据库、缓存、消息代理和流引擎。Redis 提供数据结构,例如字符串、哈希、列表、集、带有范围查询的排序集、位图、超日志日志、地理空间索引半径查询。 Redis 内置了复制、Lua 脚本、LRU 驱动事件、事务和不同级别的磁盘持久性,并通过 Redis Sentinel 和 Redis 集群的自动分区提供高可用性。
Redis-Key
127.0.0.1:6379> set name lisi # set key
OK
127.0.0.1:6379> keys * # 查看所有key
1) "name"
127.0.0.1:6379> set age 1
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
(integer) 1
127.0.0.1:6379> keys *
1) "age"
127.0.0.1:6379> set name lisi
OK
127.0.0.1:6379> keys *
1) "name"
2) "age"
127.0.0.1:6379> get name
"lisi"
127.0.0.1:6379> expire name 10 #设置过期时间 单位是seconds
(integer) 1
127.0.0.1:6379> ttl name
(integer) -2 # -2表示已过期
127.0.0.1:6379> type age # 查看当前key的类型
string
遇到不会的命令可以查看官网:redis命令手册
String
90%的Java程序员使用Redis只会使用String类型
127.0.0.1:6379> set key1 v1 #设置值
OK
127.0.0.1:6379> get key1 # 获得值
"v1"
127.0.0.1:6379> exists key1 #判断某个key是否存在
(integer) 1
127.0.0.1:6379> append key1 "hello" #追加字符串,如果不存在则新建一个key
(integer) 7
127.0.0.1:6379> get key1
"v1hello"
127.0.0.1:6379> strlen key1 #获取key的长度
(integer) 7
127.0.0.1:6379> append key1 ",zhangsan"
(integer) 16
127.0.0.1:6379> get key1
"v1hello,zhangsan"
127.0.0.1:6379> set views 0
OK
127.0.0.1:6379> incr views //自增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
(integer) 1
127.0.0.1:6379> incrby views 10 //设置步长 指定增量
(integer) 11
127.0.0.1:6379> decrby views 5 //设置步长 指定减量
(integer) 6
127.0.0.1:6379> set key "hello,wzt"
OK
127.0.0.1:6379> get key
"hello,wzt"
127.0.0.1:6379> getrange key 6 8 #截取字符串[6,8]
"wzt"
127.0.0.1:6379> getrange key 0 -1 #获取全部字符串,==get key
"hello,wzt"
127.0.0.1:6379> set key2 zhangsan
OK
127.0.0.1:6379> get key2
"zhangsan"
127.0.0.1:6379> setrange key2 5 xx #替换指定位置开始的字符串
(integer) 8
127.0.0.1:6379> get key2
"zhangxxn"
setex(set with expire) #设置过期时间
setnx(set if not exists) #不存在再设置(在分布式锁中会常常使用!)
127.0.0.1:6379> setex key3 30 "hello" #设置key3的值位hello 30秒后过期
OK
127.0.0.1:6379> ttl key3 #查看key3 还有多久过期
(integer) 27
127.0.0.1:6379> get key3
"hello"
127.0.0.1:6379> ttl key3
(integer) -2
127.0.0.1:6379> ttl key3
(integer) -2
127.0.0.1:6379> setnx mykey "wxxy" #如果mykey 不存在则创建mykey
(integer) 1127.0.0.1:6379> setnx mykey "MongoDB"
(integer) 0
127.0.0.1:6379> get mykey
"wxxy" #可以看到没有替换
mset / mget
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 #同时设置多个值
OK
127.0.0.1:6379> keys *
1) "k3"
2) "k2"
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)
#设置一个user:1 对象 值为json字符来保存一个对象
set user:1 {name:zhangsan,age:3}#这里的key是一个巧妙的设计 user:{id}:{filed}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"
getset 先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"
String类似的场景:value除了是字符串还可以是数字
- 计数器
- 统计多单位的数量 uid:666:follow 0
- 粉丝数
- 对象缓存存储
List
列表
在Redis中,我们可以把List玩成队列、栈、阻塞队列
所有的List操作都是L开头
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 #通过区间获取具体的值 #没有rrange!!!
1) "three"
2) "two"
127.0.0.1:6379> rpush list right #将一个值或多个值插入到列表头部(右)
(integer) 4127.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> rpop list #移除列表的最后一个元素
"right"
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"
127.0.0.1:6379> lpush list three
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> llen list #获取list长度
(integer) 3
127.0.0.1:6379> lpush list three
(integer) 4
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 2 three
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "two"
127.0.0.1:6379> flushdb
OK
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 "hello3"
(integer) 3
127.0.0.1:6379> ltrim mylist 1 2 #修剪list 让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除
OK
127.0.0.1:6379> lrange mylist 0 -1
1) "hello1"
2) "hello3"
rpoplpush 移除列表的最后一个元素,移动到新的列表中
127.0.0.1:6379> flushdb
OK
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> rpoplpush mylist myotherlist #移除列表的最后一个元素,移动到新的列表中
"hello3"
127.0.0.1:6379> lrange mylist 0 -1 #查看原来列表
1) "hello"
2) "hello1"
3) "hello2"
127.0.0.1:6379> lrange myotherlist 0 -1 #查看目标列表
1) "hello3"
lset 将列表中指定下标的值替换为另一个值,相当于update更新操作
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> exists list #判断这个列表是否存在
(integer) 0
127.0.0.1:6379> lset list 0 item #如果不存在列表,进行lset更新就会报错
(error) ERR no such key
127.0.0.1:6379> lpush list value1
(integer) 1
127.0.0.1:6379> lrange list 0 0
1) "value1"
127.0.0.1:6379> lset list 0 item #如果存在列表,更新当前下标的值
OK
127.0.0.1:6379> lrange list 0 0
1) "item"
127.0.0.1:6379> lset list 1 other #如果不存在,则会报错
(error) ERR index out of range
linsert 将某个具体的value插入到列表中某个元素的前面或者后面,如果这个数据是多个重复的,只取最前面那一个
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> rpush list "hello"
(integer) 1
127.0.0.1:6379> rpush list "hello1"
(integer) 2
127.0.0.1:6379> rpush list "hello2"
(integer) 3
127.0.0.1:6379> linsert list after "hello" "world" #插入到后面
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "hello"
2) "world"
3) "hello1"
4) "hello2"
127.0.0.1:6379> linsert list before "world" "other" #插入到前面
(integer) 5
127.0.0.1:6379> lrange list 0 -1
1) "hello"
2) "other"
3) "world"
4) "hello1"
5) "hello2"
小结
- 实际上是一个链表, before Node after,left,right都可以插入值
- 如果key不存在,创建新的链表
- 如果key存在,新增内容
- 如果移除了所有值,空链表,也代表不存在
- 在两边插入或者改动值效率最高,中间元素,相对来说效率会低一点
消息队列 Lpush Rpop
栈 Lpush,Lpop
Set
set中的值是不能重复的
set操作都是s开头
127.0.0.1:6379> sadd myset "hello" #set集合中添加元素
(integer) 1
127.0.0.1:6379> sadd myset "wzt"
(integer) 1
127.0.0.1:6379> sadd myset "wxxy"
(integer) 1
127.0.0.1:6379> smembers myset #查看指定set中所有值
1) "wxxy"
2) "hello"
3) "wzt"
127.0.0.1:6379> sismember myset hello #判断某个值是否是set中的值
(integer) 1
127.0.0.1:6379> sismember myset world
(integer) 0
127.0.0.1:6379> sadd myset "wzt" #不能添加重复的元素
(integer) 0
127.0.0.1:6379> scard myset #获取set集合中的元素个数
(integer) 3
127.0.0.1:6379> srem myset wxxy #移除set集合中指定元素
(integer) 1
127.0.0.1:6379> smembers myset
1) "hello"
2) "wzt"
set是无序不重复集合
127.0.0.1:6379> srandmember myset #随机抽取set集合中的元素
"wzt"
127.0.0.1:6379> srandmember myset
"wzt"
127.0.0.1:6379> srandmember myset
"hello"
127.0.0.1:6379> smembers myset
1) "hello"
2) "wzt"
127.0.0.1:6379> spop myset #随机删除set集合中的元素
"wzt"
127.0.0.1:6379> flushdb
OK
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 myset2 "java"
(integer) 1
127.0.0.1:6379> sadd myset2 "c++"
(integer) 1
127.0.0.1:6379> smove myset2 myset java #移动指定元素
(integer) 1
127.0.0.1:6379> smembers myset
1) "java"
2) "hello"
3) "world"
127.0.0.1:6379> smembers myset2
1) "c++"
微博、b站、抖音:共同关注(交集)
数字集合类
127.0.0.1:6379> sadd key1 a
(integer) 1
127.0.0.1:6379> sadd key1 b
(integer) 1
127.0.0.1:6379> sadd key1 c
(integer) 1
127.0.0.1:6379> sadd key2 c
(integer) 1
127.0.0.1:6379> sadd key2 d
(integer) 1
127.0.0.1:6379> sadd key2 e
(integer) 1
127.0.0.1:6379> sdiff key1 key2 #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) "c"
2) "a"
3) "d"
4) "e"
例如:某博,A用户将所有关注的人放在一个set集合中,将他的粉丝放在另一个集合中
Hash
Map集合,Key-Value
Hash集合,Key-Map(Key-<Key,Value>)
H开头的命令
127.0.0.1:6379> hset myhash field1 hello #set一个具体的key-value
(integer) 1127.0.0.1:6379> hget myhash field1 #获取一个字段值
"hello"
127.0.0.1:6379> hmset myhash field1 hello field2 world #set多个key-value
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 field2 #删除hash指定的key字段 对应的value也删除了
(integer) 1
127.0.0.1:6379> hgetall myhash
1) "field1"
2) "hello"
127.0.0.1:6379> hlen myhash #获取key字段数
(integer) 1
127.0.0.1:6379> hexists myhash field1 #判断hash中指定字段是否存在
(integer) 1
127.0.0.1:6379> hexists myhash field2
(integer) 0
127.0.0.1:6379> hkeys myhash #获取所有字段(field)
1) "field1"
2) "field2"
127.0.0.1:6379> hvals myhash #获取所有值(value0
1) "hello"
2) "world"
127.0.0.1:6379> hset myhash field2 5
(integer) 1
127.0.0.1:6379> hincrby myhash field2 1 #指定增量
(integer) 6
127.0.0.1:6379> hincrby myhash field2 -1 #相对于指定减量
(integer) 5
hash存储变更的数据
user----name、age
hset user:1 name zhangsan
hget user:1 name
hash更适合对象的存储,String更适合字符串存储
Zset
在set的基础上,增加了一个值
set k1 v1
zset k1 score1 v1
127.0.0.1:6379> zadd myset 1 one #添加一个值
(integer) 1
127.0.0.1:6379> zadd myset 2 two 3 three #添加多个值
(integer) 1
127.0.0.1:6379> zrange myset 0 -1 #遍历
1) "one"
2) "two"
3) "three"
127.0.0.1:6379> zadd salary 2500 lisi
(integer) 1
127.0.0.1:6379> zadd salary 5000 zhangsan
(integer) 1
127.0.0.1:6379> zadd salary 10000 wzt
(integer) 1
127.0.0.1:6379> zrangebyscore salary -inf +inf #显示全部用户 从小到大排序(负无穷到正无穷)
1) "lisi"
2) "zhangsan"
3) "wzt"
127.0.0.1:6379> zrangebyscore salary -inf +inf withscores # 显示全部用户并附带成绩 升序
1) "lisi"
2) "2500"
3) "zhangsan"
4) "5000"
5) "wzt"
6) "10000"
127.0.0.1:6379> zrangebyscore salary -inf 5000 withscores #显示工资小于2500的员工的升序排列
1) "lisi"
2) "2500"
3) "zhangsan"
4) "5000"
127.0.0.1:6379> zrevrangebyscore salary +inf -inf withscores #降序排列
1) "wzt"
2) "10000"
3) "zhangsan"
4) "5000"
5) "lisi"
6) "2500"
127.0.0.1:6379> zrem salary lisi #移除有序集合中的指定元素
(integer) 1
127.0.0.1:6379> zrange salary 0 -1
1) "zhangsan"
2) "wzt"
127.0.0.1:6379> zcard salary #获取有序集合中的个数
(integer) 2
127.0.0.1:6379> zadd salary 2500 lisi
(integer) 1
127.0.0.1:6379> zcount myset 1 2 #获取指定区间的成员数量
(integer) 2
127.0.0.1:6379> zcount myset 1 3
(integer) 3
ZRANGEBYSCORE zset (1 5
返回所有符合条件1 < score
应用场景:
- 班级成绩表;工资表排序
- 重要消息1 ,普通消息2, 带权重进行判断
- 排行榜应用实现 TOP N
Redis命令中心(Redis commands) -- Redis中国用户组(CRUG)