redis 简介 redis
是高性能键值对数据库,支持键值数据类型:
字符串类型
列表类型
有序集合类
散列类型
集合类型
redis
的应用场景
缓存
任务队列
应用排行榜
网站访问统计
数据过期处理
分布式集群架构中的 session
分离
redis
五种数据类型
字符串(String)
哈希(hash)
字符串列表(list)
字符串集合(set)
有序字符串集合(sorted set)
存储 String
二进制安全的,存入和获取的数据相同。
Value
最多可以容纳的数据长度是 512M
redis 基本操作 String 类型 Hash 类型 存入键值对, 将 username:jack
存入 myhash
中
1 2 hset myhash username jack hset myhash age 20
一次存入多个键值对
1 hmset myhash2 username rose age 21
根据键获取值
返回
根据多个键获取值
1 hmget myhash2 username age
返回
获取所有键值对
删除某个键值对
1 hdel myhash2 username age
返回
1 2 3 4 1) "username" 2) "jack" 3) "age" 4) "20"
对某个数字进行增加:将 age
属性递增5。
返回
rose 的 age
属性由 21
增加到 26
判断某个set中是否含有某个键
获取 hash 中的所有键
运行结果为:
获取 hash 中的所有值
运行结果为
List 类型 往 list
中存储数据(从左侧添加,先进去的数据排在最后一位)
1 2 lpush mylist a b c lpush mylist 1 2 3
从右侧添加 (从右侧添加)
1 2 rpush mylist2 a b c rpush mylist2 a b c
查看列表 表示从第一个到第六个元素
运行结果如下
1 2 3 4 5 6 1) "3" 2) "2" 3) "1" 4) "c" 5) "b" 6) "a"
表示从第一个到倒数第一个元素
运行结果如下
1 2 3 4 5 6 1) "a" 2) "b" 3) "c" 4) "1" 5) "2" 6) "3"
左边弹出
运行结果
右边弹出
运行结果
lpushx
和 rpushx
仅当需要操作的 list 中有值时才进行保存操作
现在 mylist3
的数据如下
1 2 3 4 5 6 7 8 9 10 11 1) "5" 2) "3" 3) "2" 4) "3" 5) "7" 6) "6" 7) "3" 8) "5" 9) "4" 10) "2" 11) "1"
移除命令 lrem
从左侧开始删除两个3
运行后的 mylist3
结果
1 2 3 4 5 6 7 8 9 1) "5" 2) "2" 3) "7" 4) "6" 5) "3" 6) "5" 7) "4" 8) "2" 9) "1"
从后边往前删除两个1
运行后的 mylist3
结果
1 2 3 4 5 6 7 8 1) "5" 2) "2" 3) "7" 4) "6" 5) "3" 6) "5" 7) "4" 8) "2"
删除所有2
运行后的 mylist3
结果
1 2 3 4 5 6 1) "5" 2) "7" 3) "6" 4) "3" 5) "5" 6) "4"
给某个指定的角标位置的元素设置值
运行结果如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 127.0.0.1:6379> lrange mylist 0 -1 1) "2" 2) "1" 3) "c" 4) "b" 5) "a" 127.0.0.1:6379> lset mylist 3 haha OK 127.0.0.1:6379> lrange mylist 0 -1 1) "2" 2) "1" 3) "c" 4) "haha" 5) "a"
新建一个 list
1 2 3 4 5 6 7 8 9 10 127.0.0.1:6379> lrange mylist4 0 -1 1) "c" 2) "b" 3) "a" 4) "c" 5) "b" 6) "a" 7) "c" 8) "b" 9) "a"
在第一个 b
之前插入 11
1 2 3 4 5 6 7 8 9 10 11 12 13 127.0.0.1:6379> LINSERT mylist4 before b 11 (integer ) 10 127.0.0.1:6379> lrange mylist4 0 -1 1) "c" 2) "11" 3) "b" 4) "a" 5) "c" 6) "b" 7) "a" 8) "c" 9) "b" 10) "a"
在第一个 b
之后插入 22
1 2 3 4 5 6 7 8 9 10 11 12 13 14 127.0.0.1:6379> LINSERT mylist4 after b 22 (integer ) 11 127.0.0.1:6379> lrange mylist4 0 -1 1) "c" 2) "11" 3) "b" 4) "22" 5) "a" 6) "c" 7) "b" 8) "a" 9) "c" 10) "b" 11) "a"
创建两个 list
1 2 3 4 5 6 7 8 127.0.0.1:6379> lrange mylist5 0 -1 1) "c" 2) "b" 3) "a" 127.0.0.1:6379> lrange mylist6 0 -1 1) "3" 2) "2" 3) "1"
现在讲 mylist5
右左边弹出,从左侧压入 mylist6
rpop
和 lpush
用于消息队列
1 2 3 4 5 6 7 8 9 10 127.0.0.1:6379> RPOPLPUSH mylist5 mylist6 "a" 127.0.0.1:6379> lrange mylist5 0 -1 1) "c" 2) "b" 127.0.0.1:6379> lrange mylist6 0 -1 1) "a" 2) "3" 3) "2" 4) "1"
Set 类型 set
类型不允许出现相同的操作,set
通常用作
跟踪一些唯一性数据
用户维护数据对象之间的关联关系
创建一个 set
并添加一个元素
1 2 3 sadd myset a sadd myset 1 2 3 sadd myset 1 2
查看所有元素发现没有重复元素
1 2 3 4 5 127.0.0.1:6379> SMEMBERS myset 1) "3" 2) "1" 3) "a" 4) "2"
查看一个元素是否存在于某个集合
1 2 3 4 127.0.0.1:6379> SISMEMBER myset a (integer) 1 127.0.0.1:6379> SISMEMBER myset x (integer) 0
说明 myset
中包含 a
,但不包含 x
创建两个 set
1 2 3 4 5 6 7 8 9 127.0.0.1:6379> SMEMBERS mya1 1) "b" 2) "c" 3) "a" 127.0.0.1:6379> SMEMBERS myb1 1) "2" 2) "1" 3) "c" 4) "a"
找出 mya1
中有,但是 myb1
中没有的元素
1 2 127.0.0.1:6379> sdiff mya1 myb1 1) "b"
找出 myb1
中有,但是 mya1
中没有的元素
1 2 3 127.0.0.1:6379> sdiff myb1 mya1 1) "1" 2) "2
将 sdiff
产生的结果直接保存
1 2 3 4 127.0.0.1:6379> SDIFFSTORE my1 mya1 myb1 (integer ) 1 127.0.0.1:6379> SMEMBERS my1 1) "b"
找出 mya1
,myb1
中都有的元素
1 2 3 127.0.0.1:6379> SINTER mya1 myb1 1) "c" 2) "a"
将上面的结果直接存储
1 2 3 4 5 127.0.0.1:6379> SINTERSTORE my2 mya1 myb1 (integer ) 2 127.0.0.1:6379> SMEMBERS my2 1) "a" 2) "c"
列出 mya1
和 myb1
的所有元素
1 2 3 4 5 6 127.0.0.1:6379> SUNION mya1 myb1 1) "b" 2) "c" 3) "2" 4) "a" 5) "1"
将上面的结果直接保存
1 2 3 4 5 6 7 8 127.0.0.1:6379> SUNIONSTORE my3 mya1 myb1 (integer ) 5 127.0.0.1:6379> SMEMBERS my3 1) "b" 2) "c" 3) "2" 4) "a" 5) "1"
查看 set
中元素的个数
1 2 127.0.0.1:6379> SCARD mya1 (integer ) 3
随机返回 set
中的一个元素
1 2 3 4 5 6 127.0.0.1:6379> SRANDMEMBER mya1 "b" 127.0.0.1:6379> SRANDMEMBER mya1 "a" 127.0.0.1:6379> SRANDMEMBER mya1 "c"
sorted set sorted set
中每一个元素都有一个分数与之关联,redis
正是通过这些分数来为 set
排序,sorted set
元素是有序的.
可以用于:
大型游戏的积分排行榜
构建索引数据
添加元素
1 2 3 4 5 6 7 127.0.0.1:6379> ZADD mysort 70 zs 80 ls 90 ww (integer ) 3 // 如果 set 中已经包将要添加的元素,执行添加命令将覆盖原来的分数 127.0.0.1:6379> ZADD mysort 100 zs (integer ) 0 127.0.0.1:6379> ZADD mysort 60 tom (integer ) 1
展示元素的分数
1 2 127.0.0.1:6379> ZSCORE mysort zs "100"
移除元素
1 2 127.0.0.1:6379> zrem mysort tom ww (integer ) 2
查看元素的个数
1 2 127.0.0.1:6379> ZCARD mysort (integer ) 2
再添加两个元素
1 2 127.0.0.1:6379> zadd mysort 85 jack 95 rose (integer ) 2
展示所有元素
1 2 3 4 5 127.0.0.1:6379> ZRANGE mysort 0 -1 1) "ls" 2) "jack" 3) "rose" 4) "zs"
展示所有元素和分数
1 2 3 4 5 6 7 8 9 127.0.0.1:6379> ZRANGE mysort 0 -1 withscores 1) "ls" 2) "80" 3) "jack" 4) "85" 5) "rose" 6) "95" 7) "zs" 8) "100"
按分数从大到小排列
1 2 3 4 5 6 7 8 9 127.0.0.1:6379> ZREVRANGE mysort 0 -1 withscores 1) "zs" 2) "100" 3) "rose" 4) "95" 5) "jack" 6) "85" 7) "ls" 8) "80"
删除排序从 0 到 3 的元素
1 2 3 4 5 6 7 8 9 10 11 12 127.0.0.1:6379> ZRANGE mysort 0 -1 1) "bruce" 2) "perter" 3) "clark" 4) "arrow" 5) "wonder" // 删除了排名 0 到 2 的元素 127.0.0.1:6379> ZREMRANGEBYRANK mysort 0 2 (integer ) 3 127.0.0.1:6379> ZRANGE mysort 0 -1 1) "arrow" 2) "wonder"
新增几个元素
1 2 3 4 5 6 7 8 9 10 11 127.0.0.1:6379> zrange mysort 0 -1 withscores 1) "arrow" 2) "40" 3) "wonder" 4) "50" 5) "bruce" 6) "60" 7) "clark" 8) "70" 9) "peter" 10) "80"
查找分数在 40 到 70 分区间的前两个元素
1 2 3 4 5 127.0.0.1:6379> ZRANGEBYSCORE mysort 40 70 withscores limit 0 2 1) "arrow" 2) "40" 3) "wonder" 4) "50"
增加分数
1 2 127.0.0.1:6379> ZINCRBY mysort 7 arrow "47"
查找某个分数段内元素的个数
1 2 127.0.0.1:6379> ZCOUNT mysort 50 80 (integer ) 4
redis的keys基本操作 查找所有的 keys
1 2 3 4 5 6 127.0.0.1:6379> keys * 1) "myhash2" 2) "hahaha" 3) "mylist2" 4) "myhashset2" ...
查看以 my
开头的所有的 key
1 2 3 4 127.0.0.1:6379> keys my? 1) "my3" 2) "my2" 3) "my1"
删除 keys
1 2 127.0.0.1:6379> del my1 my2 my3 (integer ) 3
判断某个 key 是否存在
1 2 3 4 127.0.0.1:6379> EXISTS hahahs (integer ) 0 127.0.0.1:6379> EXISTS mysort (integer ) 1
重命名key
1 2 3 4 5 6 7 8 9 10 11 12 127.0.0.1:6379> get compnay "immooc" 127.0.0.1:6379> RENAME compnay (error) ERR wrong number of arguments for 'rename' command 127.0.0.1:6379> RENAME compnay newcompany OK // 重命名之后就获取不到了 127.0.0.1:6379> get compnay (nil) // 使用新的名字获取 127.0.0.1:6379> get newcompany "immooc"
设置超时时间 单位秒
1 2 3 4 5 127.0.0.1:6379> EXPIRE newcompany 1000 (integer ) 1 // 查看剩余超时时间 127.0.0.1:6379> ttl newcompany (integer ) 989
查看 key 的类型
1 2 3 4 5 6 7 8 9 10 127.0.0.1:6379> type newcompany string 127.0.0.1:6379> type mylist list 127.0.0.1:6379> type myhash hash 127.0.0.1:6379> type mysort zset 127.0.0.1:6379> type myset set
redis 的事务 一个 redis 实例可以包含 15 个数据库,下标是从 0-15,默认选择第 0 号数据库
切换数据库命令如下
1 2 3 4 127.0.0.1:6379> select 1 OK 127.0.0.1:6379[1]> keys * (empty list or set )
可以看到 1 号数据库中没有保存任何的key
将 0 号数据库中的一个 key 移动到 1 号数据库
1 2 3 4 5 6 127.0.0.1:6379> MOVE mysort 1 (integer ) 1 127.0.0.1:6379> select 1 OK 127.0.0.1:6379[1]> keys * 1) "mysort"
multi
相当于开启事务
开启事务后,输入的命令将被保存的队列中
exec
相当于 commit
1 2 3 4 5 6 7 8 9 10 11 12 127.0.0.1:6379> get num "65" 127.0.0.1:6379> multi OK 127.0.0.1:6379> incr num QUEUED 127.0.0.1:6379> incr num QUEUED 127.0.0.1:6379> exec 1) (integer ) 66 2) (integer ) 67 127.0.0.1:6379>
执行之后命令队列中的命令将会被全部执行
discard
相当于 rollerback
redis 持久化概述 redis
之所以效率很高是因为数据都保存在内存中,为了使 redis
重启之后数据不丢失,就需要将 redis
数据保存到硬盘上。
redis
持久化有两种方式:
持久化的使用方式
RDB 持久化:定期保存 redis
的快照到硬盘
AOF 通过日志记录 redis
的命令,每次重启之后读取这个文件来重现 redis
之前的状态
无持久化:单纯将 redis
作为一个缓存服务
同时使用 RDB 和 AOF
RDB 方式 在 redis.conf
文件中可以指定保存快照的时机
1 2 3 save 900 1 save 300 10 save 60 10000
AOF 方式
需要在 redis.conf
中打开配置
1 2 3 4 5 6 7 8 9 10 # aof 是否打开 默认是关闭的 需要改为 yes appendonly yes appendfilename "appendonly.aof" # 每次操作都同步日志 # appendfsync always # 每秒同步记录一次 appendfsync everysec # 不同步 # appendfsync no
SringBoot Redis 重要注解 Spring-boot
引入 redis
缓存机制,首先需要在启动类上增加一个注解
在 controller
的方法上增加 @Cacheable
注解,一般用于查询接口
@Cacheable(cacheNames = "product", key = '#sellerId', condition="#sellerId.length>3", unless = "#result.getCode()!=0")
#sellerId
的写法成为 spel
表达式,获取参数 sellerId的值
当 sellerId
的字符长度大于 3 ,而且 除了 返回的 code!=0(也就是等于0都缓存)
当数据改变之后表用 @Cacheput
注解修改缓存,通常用于保存或者修改方法
@CachePut
要使用上面两个注解更新缓存 必须保证方法的返回值一致
如果上面两个注解的 key 不填或者为空,则key默认为方法的参数,这就会导致 key不一致的问题(即使方法的返回值一致)
可以把 cacheName
属性移到 类注解 @CacheConfig(cacheNames="product")
@CacheEvict(cacheNames = "product",key="123")
清除缓存
使用上面的缓存必须实现序列化