—— Redis简介
特点:
- 运行速度:CPU>内存>硬盘
- 用的是c语言
- 一秒写8w次,读11w次
- 不需要事先设计数据库,随取随用
- 单线程,基于内存操作
应用场景
- 分布式会话缓存
- 分布式锁
- 发布/订阅
- 排行榜/计数器
- 队列
- 全页缓存
- 缓存热点数据
大数据的3v和3高
- 3v:海量、多样、实时
- 3高:高可拓、高并发、高性能
NOSQL的四大分类
- KV键值对:Redis
- 文档型数据库(bson和json):MongoDB,介于关系型和非关系型数据库之间
- 列存储数据库:HBASE
- 图关系型数据库:不是存图片,是存关系,朋友圈社交网络,广告推荐
redis-benchmark(压力测试)命令:redis-benchmark -h localhost -p 6379 -c 100 -n 100000
更新方法:先更新数据库,再删除缓存
—— Redis数据
数据库默认个数:16
- 可使用select进行切换数据库;
- flushall:清空所有数据库;
- flushdb:清空当前数据库
数据类型:
- string:字符型
- list:有序有重复集合
- hash:散列
- set:无序无重复集合
- sorted set:有序无重复集合(排名)
- geospatial:地理位置存储
- hyperloglog:基数统计,去重
- bitmap:位图场景(状态,登录与未登录,打卡与未打开)
—— Redis事务
- Redis单条命令式保存原子性的,但是事务不保持原子性
- 开启事务:mutil
- 执行事务:exec
- 放弃事务:discard
乐观锁:认为什么时候都不会出问题,所以不会上锁,更新数据的时候去判断一下,在此期间是否有人修改过这个数据。mysql对应version,redis——watch加锁,unwatch解锁。一般读操作时加乐观锁
悲观锁:认为什么时候都会出问题,在每次拿数据的时候都上锁,多写的情况下加悲观锁
—— SpringBoot整合Redis
在SpringBoot 2.x之后,原来的Jedis被替换成了lettuce
- Jedis:采用的直连,多个线程操作的话,是不安全的,想要避免不安全,使用jedis pool连接池。像BIO模式
- lettuce:采用netty,实例可以在多个线程进行共享,不存在线程不安全的情况,可以减少线程数据。像NIO模式
- 源码分析:
springboot所以的配置类,都有一个自动配置类,redis为RedisAutoConfiguration;自动配置类都会绑定一个properties配置文件,RedisProperties - RedisTemplate序列化:
springboot有默认的RedisTemplate,自定义RedisTemplate时会覆盖;默认序列化是JDK序列化,key-value需要采用序列化形式,key中用StringRedisSerializer,value序列化采用json和ObjectMapper
——Redis持久化
- 触发机制:配置save满足情况下,执行flushall命令,退出redis
- 恢复rdb文件:将dump.rdb文件放在redis启动目录即可,redis启动时会自动检查rdb文件
Redis发布订阅:
通过subscribe命令订阅某个频道后,redis-server里就维护了一个字典,字典的键就是一个个频道,而字典里的值则是一个链表,链表中保存了订阅这个频道channel的客户端。subscribe命令就是将客户端添加到订阅这个频道的链表中。
—— Redis高可用
主从复制:
- 默认情况下,每台Redis服务器都是主机
- 搭建集群至少一主二从
- 配置命令:
slaveof 127.0.0.1 6379
(真实的主从配置是在配置文件中配置,是永久的;使用命令配置是暂时的) - 查看当前节点信息:
info replication
- 主机断开,使当前从机变为主机:
slaveof no one
(手动谋朝篡位) - 主写从读,从机不能写!主机所有数据都会自动被从机保存
- 复制原理:全量复制(从机重新连接主机,从机自动加载所有主机的数据);增量复制(主机继续将新的修改命令依次传给从机,完成同步)
哨兵模式
- 定义:能够后台监控主机是否有故障,如果故障了根据投票数自动将从机转换成主机
- 原理:开启一个独立的进程,通过发送命令,等待Redis服务器的响应,从而监控运行多个Redis 实例
- 哨兵集群:3哨兵,1主2从,除了监控各个Redis服务器之外,哨兵之间也互相监控
- 哨兵配置文件sentinel.conf:
sentinel monitor myredis 127.0.0.1 6379
(sentinel monitor 被监控名称 host port 投票数) - 开启哨兵模式:redis-sentinel sentinel.conf(配置文件路径)
- 假设主服务器宕机,哨兵1检测到这个结果,系统并不会马上进行failover(故障转移)过程,仅仅只是哨兵1主观的认为主服务器不可用,这个现象称为主观下线;当后面的哨兵也检测到主服务器不可用,哨兵集群发起投票,超过一半,进行failover操作。切换成功后,通过发布订阅模式,让各个从机切换主机,这个过程称为客观下线
主从复制(一主一从)
- master 宕机后,需手动连接slave客户端,输入
slaveof no one
,将 slave 切换成主机 - master 再次连接上后,master 和 slave 成为两个单独的数据库
- slave 宕机后重启,则可再次成为 master 的从机
哨兵(主备)模式(一主一从二哨兵)
- master 宕机后,两个哨兵进行投票,自动将slave切换成主机
- 当 master 再次连接上后,成为 slave 的从机
- 当其中一个哨兵宕机后,哨兵集群无法进行选举出主哨兵(只有两个哨兵的情况下出现这种情况,三个哨兵则能正常选举)
- 不存在主哨兵时,当 master 宕机后,无法进行备用机切换
集群conf文件配置:
- port 6379(修改端口号)
- daemonize yes (开启后台运行)
- pid /var/run/redis_6379.pid (后台进程文件)
- logfile “6379.log” (日志文件)
- dbfilename dump6379.rdb (rdb文件)
- linux启动redis:redis-server redis.conf(redis.conf文件路径)
引发的问题
- 缓存穿透:缓存和数据库都不存在的key,流量过高导致DB挂掉
解决方案:- 缓存空对象(常用):访问key未在DB查询到的值,也将空值写进缓存,但设置过期时间
- 布隆过滤器:是一种数据结构,对所有可能查询的参数以hash形式进行存储,在控制层先进行校验,不存在的key直接被过滤掉
- 缓存击穿:缓存中没有,数据库中有,直接去数据库中取数据,数据库压力过大导致挂掉(并发查询一条数据)
解决方案:设置热点数据永不过期;加互斥锁(Redisson分布式锁) - 缓存雪崩:缓存中数据大批量到期时间,查询的数据量大,数据库压力大导致宕机
解决方案:缓存数据过期时间随机;热点数据永不过期
—— 其他
Redis配置文件conf:
- daemonize yes(以守护进程的方式运行,默认是no,改为yes是后台运行)
- save 900 1 (如果900s内改变1次,就进行保存快照,持久化操作)
- bind 127.0.0.1 (绑定ip)
淘汰策略
- voltile-lru:
从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰 - volatile-ttl:
从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰 - volatile-random:
从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰 - allkeys-lru:
从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰 - allkeys-random:
从数据集(server.db[i].dict)中任意选择数据淘汰 - no-enviction(驱逐):
禁止驱逐数据
删除策略
- 定时删除:定时删除策略通过使用定时器,定时删除策略可以保证过期键尽可能快地被删除,并释放过期键占用的内存。然而,如果服务器创建大量的定时器,服务器处理命令请求的性能就会降低,因此Redis目前并没有使用定时删除策略。
- 惰性删除:惰性删除策略只会在获取键时才对键进行过期检查,不会在删除其它无关的过期键花费过多的CPU时间。该策略是惰性删除和定时删除的一个折中,既避免了占用大量CPU资源又避免了出现大量过期键不被清除占用内存的情况。
删除 和 淘汰策略两者区别
- 触发条件:删除策略基于键的过期时间,当键过期时自动删除;而淘汰策略基于内存使用情况,当内存不足时触发。
- 适用场景:删除策略用于自动管理键的过期时间,适用于需要自动删除过期键值对的场景;淘汰策略用于在内存不足时主动选择部分键值对进行淘汰,适用于在内存限制下保障Redis的稳定性和性能的场景。
Redis && Memcached
springboot整合redis产生的问题
- springboot2.0 以后默认使用 lettuce 作为操作redis客户端,它是使用 netty 进行网络通信
- lettuce的 bug 导致 netty 堆外内存溢出 OutOfDirectMemoryError
- 解决方案:
- 升级 lettuce 客户端
- 切换老版本的 jedis
- lettuce 和 jedis 都是操作redis的底层客户端,redisTemplate 是 springboot 再次封装
本地连接Redis客户端
- 集群连接
redis-cli.exe -c -h rediscloud1.steelphone.mysteel.local -p 7051
- 队列查询
zrange newspider:wxCookie:delayQueue 0 10