Redis相关
Redis
使用场景
- 数据库缓存,减轻服务器压力,提高系统响应。当系统访问量太大,数据库压力增大,使用redis将访问过的内容或者数据存储起来,再次访问的时候先找缓存,缓存命中返回数据,不命中再找数据库,并回填数据。
- session分离。集群或者分布式环境不同web容器管理自己的session,自带的session共享通过网络和IO进行同步,极大地影响性能。
- 实现分布式锁。sexNX
- 实现乐观锁。watch+incr
数据类型及使用场景
Redis以K-V方式存储KEY的类型是字符串,Value的数据类型有:
String、list、set 、sortedset(zset)有序集合、hash、stream 处理消息、bitmap位图、geo地理位置
String:一个字符串value最多可以存512M。
事务
redis事务是一个单独的隔离操作,事务中所有的命令都会序列化、按顺序执行、执行过程中不会被其他客户端发送来的命令打断。主要作用就是串联多个命令,防止别的命令插队。
multi 开启事务==>输入命令==>exec 开始执行。期间可使用discard取消。
如果期间输入时失败,所有命令全部失效
如果是输入正确 但是执行期间错误,则只有错误的失效 其他正常执行
参考 编译阶段错误直接不能运行,编译成功,运行期间错误
特性
单独的隔离操作
事务中所以命令都会序列化、按顺序执行
没有隔离级别
队列中那个命令在没有提交之前都不会实际被执行,因为事务提交前任何指令都不会被实际执行
不保证原子性
事务中如果有一条命令执行失败,其后的命令任然会被执行,没有回滚。
Redis秒杀实现
实现
- 获取库存,如果库存null 则还没有开始。
- 判断用户是否重复秒杀动作
- 判断商品数量,库存数量小于1,秒杀结束
- 秒杀过程
- 库存-1
- 存储秒杀成功用户
测试 yum install httpd-tools -y
ad -n 10000 -c 1000 http://www.baidu.com/?
连接超时
使用连接池。
超卖问题
使用乐观锁事务
- 使用redis
watch
监视库存 - 事务
multi
中执行update操作
库存遗留问题
库存多了,但是秒杀结束库存还剩余。这是由于乐观锁造成,因为版本号不一致。
解决:使用LUA脚本(redis.version>2.6)
利用redis单线程特性,用任务队列的方式解决多任务并发问题。
持久化操作
RDB
在指定的时间间隔内将内存中的数据集快照写入磁盘(dump.rdb)。
流程
单独创建(fork)子进程—同步数据到临时缓冲区,然后再替换dump.rdb持久化文件:写时复制
优势:周期性大规模备份
缺点:因为是周期性,所以最后一次持久化的数据可能会,因为会复制一份所以空间需要考虑
丢失。
触发:配置文件中配置 save、执行save命令或者bgsave
bgsave会在后在后台异步进行快照操作,快照同时可以响应客户端请求。
AOF
以追加日志的形式来对每个写操作做增量保存,不记录读操作,redis启动时会读取改文件重新构建数据,也就是说重启后会根据日志内的写指令完整执行一次来恢复数据。
AOF默认不开启,需要在配置文件中手动开启appendonly yes
如果同事开启RDB AOF 系统默认取AOF的数据(因为数据不会丢失)
如果AOF文件损坏 可以通过redis-check-aof —fix 修复
流程
- 写命令会被append追加到AOF缓冲区
- AOF缓冲区根据AOF持久化策略将操作sync同步到磁盘的AOF中
- 当文件大小超过重写策略或者手动重写时,会对AOF文件重写,压缩AOF文件容量。
- 重启服务时会加载AOF文件恢复数据。
比RDB占用更多空间
推荐
官方推荐都启用
如果数据不敏感可以单独选用RDB
主从复制
主机数据更新后根据配置和策略自动同步到备机,Master写为主,Slave读为主
读写分离性能扩展。
快速恢复
应用问题解决
- 缓存穿透:请求多,命中率降低,数据库压力大。
- 对空值缓存,但是如果每次请求的KEY是随机的,这种处理无效
- 使用布隆过滤器,判断某个key是否存在。
- 实时监控报警。
- 缓存雪崩: 某一时刻大量缓存失效,导致数据库压力巨大,可能宕机,如果这时候启动数据库又有新的流量冲击数据库,造成再次宕机。
- 在失效时间上加随机值,避免因同一时间过期导致雪崩
- 熔断,当流量达到一定的阈值,进行限流。
- 提高数据库
- 缓存击穿:雪崩是大规模KEY失效,击穿是个别的KEY失效并且有大量请求,造成数据库崩溃。
- 可考虑设置KEY不过期
- 使用互斥锁。如果缓存失效,只有拿到锁才可以查询数据库。但是这样性能会变差。
分布式锁
通过setnx
设置锁,用del
释放锁
问题:如果锁一直未释放,可以设置过期时间解决这个问题expire
set user 10 nx ex 10
上锁+设置过期时间 同步进行
缓存与数据库一致性
更新策略
- 理由redis的缓存淘汰策略被动更新 例如LRU
- TTL被动
- 更新数据库时主动更新(先更数据库再删缓存—延时双删)
- 异步更新定时任务,数据不保证实时性