一、Redis安装
我是使用docker安装的,首先在/usr/local/docker目录下创建redis目录
cd /usr/local/docker
mkdir redis,在redis目录下创建data目录和新建redis.conf文件
进入redis.conf文件,把在网上找到的redis配置文件复制进自己的文件
修改启动默认配置(从上至下依次):
bind 127.0.0.1 #注释掉这部分,这是限制redis只能本地访问
protected-mode no #默认yes,开启保护模式,限制为本地访问
daemonize no#默认no,改为yes意为以守护进程方式启动,可后台运行,除非kill进程,改为yes会使配置文件方式启动redis失败
databases 16 #数据库个数(可选),我修改了这个只是查看是否生效。。
dir ./ #输入本地redis数据库存放文件夹(可选)
appendonly yes #redis持久化(可选)
requirepass 密码 #配置redis访问密码
配置完成之后启动redis
docker run -p 6379:6379 --name demoredis --privileged=true -v /usr/local/docker/redis/redis.conf:/etc/redis/redis.conf -v /usr/local/docker/redis/data:/data -d redis redis-server /etc/redis/redis.conf --appendonly yes
docker ps查看redis是否启动成功,如果不成功则
docker logs demoredis 查看日志,处理问题后再次启动
进去redis客户端。 docker exec -it redis redis-cli
二、Redis基本操作
五大数据类型
1、String
String底层是动态字符串,可以类似StringBuffer
set key value 普通的存值,如果key相同会覆盖
get key 取值
append key value 将value追加到key的末尾
strlen key 获取key的长度
setnx key value 加锁,没有key时才能成功
incr key 加一,只对数字类型有用
decr key 减一,只对数字类型有用
incrby key num 把key增加num
decrby key num 把key减少num
mset k1 v1 k2 v2 k3 v3 设置多个key,value
mget k1 k2 k3 取多个值
msetnx k1 v1 k2 v2 k3 v3 设置多个锁,只有所有key都不存在才成功
setex k1 timeout v1 设置值和过期时间timeout
2、List
底层是双向链表
lpush/rpush key v1 v2 v3 向左边/右边加入多个值
lpop/rpop key 从左边/右边拿出一个值,全部取出之后key消失
rpoplpush k1 k2 从k1右边拿出一个值插入k2左边
lrang key start end 从key中取一定范围的值,0表示左边第一个,-1表示右边第一个,0 -1表示取所有值
lindex key index 从key中取出该下标的值,从0开始
llen key 获取列表长度
linsert key before value newvalue 在值的后面加入新值
lrem key n value 删除n个值为value的数据
lset key index value 将下标值替换成value
3、set
数据结构是dict字典,字典是用哈希表实现的
sadd key v1 v2 v3 将一个或多个元素加入到集合,重复的会忽略
smembers key 取出该集合所有值
sismember k1 v1 判断k1中是否有v1
scard key 集合中的个数
srem key v1 v2 删除集合中的值
spop key 随机从集合中取出一个值,会从集合删除
srandmember key n 随机取出n个值,不会从集合删除
sinter k1 k2 返回两集合的交集
sunion k1 k2 返回两集合的并集
sdiff k1 k2 返回两集合的差集
4、hash
对应的数据结构有两种,ziplist和哈希表,当field-value长度长时用哈希表
hset key field value 给key中的field属性赋值,可以多次给key添加属性
hget key field 从key中取出field的值
hmset key f1 v1 f2 v2 批量设置属性值
hexist key field 判断key中是否有该属性
hkeys key 查看key的所有属性
hvals key 查看key的所有属性值
hincrby key field n 给key的属性加n
5、zset有序集合
底层是hash和跳表
zadd key s1 v1 s2 v2 s3 v3 向key集合加入s评分和值,根据评分从小到大排序
zrange key start end 返回key集合的元素
zrangebyscore key s1 s2 withscores 返回评分s1到s2之间的值
zincrby key n value 给key集合的value加上n
zrem key value 删除指定值
zcount key s1 s2 返回key集合评分在s1到s2之间的个数
zrank key value 返回该值在key集合中的排名,从0开始
三、发布和订阅
redis发布订阅(pub/sub)是一种消息通信模式:发送者pub发送消息,订阅者sub接受消息
redis客户端可以订阅任意数量的频道
在Xshell6中打开两个页面,用于发布和订阅
docker ps查看redis是否运行
docker exec -it demoredis /bin/bash进入目录
redis-cli开启一个客户端,先订阅一个频道
subscribe channel1
如果配置了密码,此处会报错
此时需要auth password(此处为你设置的密码)重新加载一下权限才能使用
此时redis客户端就已经订阅了channel1频道
另外一个客户端也是同样进入docker的redis目录
redis-cli
auth password(此处为你设置的密码)
publish channel1 hello 发布消息到channel1频道
切回第一个redis客户端
成功接收到hello
四、新数据类型
1、Bitmaps
bitmaps是专门进行位操作的字符串
setbit key offset value 设置key在某个偏移量上的值,只能为0 1
getbit key offset 获取key在该偏移量上的值
bitcount key 返回值被设置为1的个数
bitcount key start end 返回两参数之间值被设置为1的个数-1表示最后一位
bitop and(or/not/xor) destkey k1 k2 复合操作,and(交集),or(并集),not(非),xor(异或),并将结果保存在destkey中
bitmaps更加节约内存
2、HyperLogLog
用于做基数(不重复元素)统计
pfadd key value 向key中加入数据,可以多次添加,数量加1,添加重复value不加1
pfcount key 返回key中的基数个数
pfmerge destkey k1 k2 将k1和k2合并到destkey中
3、Geospatial
用于存放经纬度
geoadd key 经度 纬度 value 设置key中的value的经纬度
geopos key value 获取经纬度
geodist key v1 v2 km 获取两个地点之间的距离,单位位km(千米),单位有m(米),km(千米),mi(英里),ft(英尺),不设置默认为m
georadius key 经度 纬度 num km 取到key在该经纬度num千米内的值
五、Java中使用Redis
1、Jedis使用
1、准备工作
在pom文件中导入jedis依赖
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>4.1.1</version> </dependency>
在springboot中测试jedis
输入你虚拟机的ip和6379端口,虚拟机防火墙要开放此端口
firewall-cmd --add-port=6379/tcp --permanent
firewall-cmd --reload
并且在redis.conf配置文件中一定要注释bind 127.0.0.1,并且设置protected-mode no
如果设置了密码,还要在jedis中设置密码
jedis.auth("password");
运行成功,控制台打印 PONG
2、java中使用Jedis
运行如果报错,检查redis是否能正常连接,key是否存在
1、key操作
2、list操作
3、set操作
4、hash操作
5、zset操作
Jedis中的方法大多和Redis中一致,可以自己尝试
3、模拟验证码发送
为了测试,代码都写在一起,基本流程如上,实际业务中需要修改
2、springboot整合redis
1、准备工作
在springboot的pom文件中导入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <version>2.6.3</version> </dependency>
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.13.1</version> </dependency>
编写配置文件application.yml
spring: redis: #Redis服务器地址 host: 192.168.81.130 #Redis设置的密码 password: 100940 #Redis数据库索引(默认位0) database: 0 #连接超时时间(毫秒) timeout: 1800000 lettuce: pool: #连接池最大连接数(使用负值表示没有限制) max-active: 20 #最大阻塞等待时间(负数表示没有限制) max-wait: -1 #连接池中的最大空闲连接 max-idle: 5 #连接池中的最小空闲连接 min-idle: 0
新增redis的配置类,配置redisTemplate
@EnableCaching //开启缓存 @Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); RedisSerializer<String> redisSerializer = new StringRedisSerializer(); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper objectMapper = new ObjectMapper(); objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY); jackson2JsonRedisSerializer.setObjectMapper(objectMapper); template.setConnectionFactory(factory); //key采用String的方式序列化 template.setKeySerializer(redisSerializer); //value序列化方式采用jackson template.setValueSerializer(jackson2JsonRedisSerializer); //hash序列化方式采用jackson template.setHashValueSerializer(jackson2JsonRedisSerializer); return template; } }
创建controller类测试
六、Redis的事务和锁机制
1、事务
multi指令,将接下来的操作放入队列中
exec指令,将队列中的操作执行
discard指令,取消队列中的操作
组队期间报错,exec执行不成功
组队期间不报错,单条语句报错,其他语句执行,报错语句不执行
2、锁机制
watch key 加乐观锁,可以加多个key
乐观锁适用于多读的应用类型,这样可以提高吞吐量
3、模拟秒杀
yum install httpd-tools 下载ab工具
ab -n 1000 -c 100 http://192.168.1.91:8080/test 表示请求1000次,100个并发,ip为本机ip,不是虚拟机ip
七、Redis持久化
1、RDB
单独创建一个Fork进程来保存数据副本,等副本全部保存完成,才会替换到Redis中的dump.rdb文件,保证数据的完整性,RDB最后一次操作的数据可能会丢失
2、AOF
以日志的形式记录每个写操作,将Redis执行过的写指令记录下来,追加文件不允许改文件,AOF默认是不开启的,需要修改配置文件appendonly yes
AOF有文件自动修复功能
redis-check-aof --fix appendonly.aof 执行修复操作
AOF和RDB同时开启,系统默认读取AOF数据
八、Redis主从复制
读写分离,主机以写为主,从机以读为主
在linux中创建目录,/usr/local/docker/redis6380和/usr/local/docker/redis6381
分别在两个目录创建data文件夹和redis.conf配置文件,其中配置文件的端口号需要修改,masterauth需要添加
开启三个Redis,端口分别为6379,6380,6381
docker run -p 6380:6380 --name demoredis2 --privileged=true -v /usr/local/docker/redis6380/redis.conf:/etc/redis/redis.conf -v /usr/local/docker/redis6380/data:/data -d redis redis-server /etc/redis/redis.conf --appendonly yes
docker run -p 6381:6381 --name demoredis3 --privileged=true -v /usr/local/docker/redis6381/redis.conf:/etc/redis/redis.conf -v /usr/local/docker/redis6381/data:/data -d redis redis-server /etc/redis/redis.conf --appendonly yes
打开三个窗口分别连上不同端口的Redis
docker exec -it demoredis /bin/bash
docker exec -it demoredis2 /bin/bash
docker exec -it demoredis3 /bin/bash
redis-cli -p 6379
redis-cli -p 6380
redis-cli -p 6381
info replication 查看主机运行情况
配从机不配主机
设置了密码需要在从机配置文件中修改masterauth选项
slaveof 192.168.81.130 6379
此时返回主机Redis查看,从机配置成功
主服务器挂掉,从服务器还是从服务器,重启之后还是变成他们的主服务器
从服务器挂掉,重启之后变回主机,需要重新slaveof配置从机
1、薪火相传
在从机中配置从机
slaveof 192.168.81.130 6380
除了从机的从机不是主机的从机外,其他的和一主多从一样
2、反客为主
slaveof no one
主机挂掉,从机会变成主机
3、哨兵模式
反客为主自动版
在redis文件夹的data文件夹中,新建sentinel.conf配置文件
在配置文件中复制以下内容
sentinel monitor mymaster 192.168.81.130 6379 1
其中mymaster为监控对象起的服务器名称,1为有一个哨兵同意迁移
进入docker的redis容器,运行以下命令
redis-sentinel sentinel.conf
九、Redis集群
当Redis存储不够,就需要水平扩容,即搭建集群
Redis3.0开始,提供了无中心化集群
任何一台服务器都可以作为入口,至少三个主节点
配置文件配置基本信息,其余的复制之后稍作修改
配置完后用docker启动这6个服务
将这6个节点配成集群
进入redis容器目录
redis-cli --cluster create --cluster-replicas 1 192.168.81.130:6379 192.168.81.130:6380 192.168.81.130:6381 192.168.81.130:6389 192.168.81.130:6390 192.168.81.130:6391
如果报错,在最后加上 -a password
如果还报错,在最后加上 2>/dev/null
如果没有反应,尝试把ip改成127.0.0.1
redis-cli -c -p 6379 -c表示采用集群策略连接,设置数据会自动切到相应的主机
cluster nodes 查看节点信息
slots插槽
Redis集群中有16384个插槽,会分配到集群中的Redis中
加入值是通过计算插槽位置来切换主机的,由于这个性质,不能用mset加入多个值
cluster keyslot key 查询key所在的插槽
cluster countkeysinslot slot 查看slot插槽里的数量,只能查看自己redis的插槽
故障恢复
Redis集群的故障恢复,主机挂了,从机成为主机,原来的主机恢复后成为从机
如果某一段插槽的主机和从机都挂了,在配置文件中有个配置
cluster-require-full-coverage
如果配置为yes,那么整个集群挂掉
如果为no,该段的插槽都不能操作,其他的可以操作
Jedis操作
因为是无中心化集群,所以随便哪个节点都能作为入口
不能进行多键操作
十、常见问题
1、缓存穿透
redis命中率降低,一直查询数据库,造成数据库压力过大
出现大量恶意请求
解决方法:
1、对空值缓存,设置很短的过期时间
2、设置可访问白名单,名单存在bitmaps中
3、进行实时监控,排查访问对象,设置黑名单
4、限流
2、缓存击穿
Redis某个热点key正好过期,数据库访问压力瞬时变大
解决方法:
1、预先设置热门数据
2、实时调整热点key的时长
3、使用锁
3、缓存雪崩
缓存大面积失效
解决方法:
1、构建多级缓存架构:nginx缓存+redis缓存+其他缓存
2、使用锁或队列
3、设置过期标志,快过期更新缓存
4、将缓存失效时间分散开
十一、实现分布式锁
setnx key value 实现分布式锁
set key value nx ex 60 实现分布式锁,同时设置60秒过期
del key 删除锁