Redis
文中内容:redis数据结构、集群(这个比较简单,具体的有时间在上传)、持久化方式、内存过期策略、内存淘汰策略、三大缓存问题、事物
简介:
redis是一种 ANSI C语言编写的,基于内存也可持久化的key-value数据库,意大利一家公司创始人2008开发2009年开发完成。
数据类型:
基本类型
- string 字符串类型
- map 散列类型
- list 列表类型
- set 集合类型
- sortedset 有序(升序)集合类型
高级数据结构
-
HyperLogLogs 基数统计的算法
-
Bitmaps
-
GEO 存储地理位置信息
1.set
特点:无序、值唯一
添加:zadd baidu 1 zhangsan
查询多个keys:zrange baidu 0 -1
场景:
1.排行榜
数据结构:
1.ziplist
1.条件:元素个数不超过128,每个元素长度不超过64
(默认可以通过修改配置文件:zset-max-ziplist-entries元素数量,zset-max-ziplist-value大小)
1.sortedset
特点:有序,可重复
添加:zadd baidu 1 zhangsan
查询多个keys:zrange baidu 0 -1
场景:
1.排行榜
数据结构:
1.ziplist
1.条件:元素个数不超过128,每个元素长度不超过64
(默认可以通过修改配置文件:zset-max-ziplist-entries元素数量,zset-max-ziplist-value大小)
2.skiplist
2.HyperLogLogs(去重、不会存储元素本身、一共三个命令、计算基数时间O(n) )
添加:pfadd baidu2 lll
查询key的数量:pfcount baidu2
合并多个这个数据类型的ke值,一个新的key上:pfmerge
场景:
1.uv 、日月活用户统计
2.统计注册 IP 数
3.统计每日访问 IP 数
4.统计在线用户数
5.统计用户每天搜索不同词条的个数
优点:
1.占用空间最大12kb
缺点:
1.无法获取具体元素值,只能计算基数
2.bitmap(只能存储0、1)
场景(只有两个状态的场景):
1.签到打卡
3.GEO
添加:GEOADD cities 经度 维度 城市 经度 维度 城市
查询指定城市的距离(默认为米):GEODIST cities 城市 城市 km(计算出来为千米值)
计算指定半径的城市:GEORADIUS cities 经度 纬度 半径(默认米) [m|km|ft|mj](公里)
查询城市的经度纬度:GEOPOS cities 城市 …
4.list
结构:快速列表=kiplist+list
场景:
1.查看最新的消息
2.生产者/消费者模式
5.set
特点:无序、去重
结构:
1.inset整数集合(数据量不大,元素多事整数)
2.字典
场景:随机发牌、spop随机去一个元素、记录ip、唯一的信息
持久化:
将redis存在内存中的数据,持久化到磁盘中,保证数据不丢失。
- rdb (redis date base)
- aof
- rdb、aof混合存储 (4.0版本后支持)
1.【rdb】(快照保存,非增量)
优点:
1.恢复速度快
缺点:
1.未达到保存条件时,服务异常关闭,将不能持久化之前写入的数据
2.内存中数据量大,保存一次会影响性能
3.redis不同版本有多个rdb文件的版本,不支持跨版本兼容
触发时机:
1.手动触发:save/bgsave
2.自动触发:满足redis配置文件中的自动触发条件(比如我们设置的:至少60s有5次更新就会触发RDB文件生成,是bgsave方式保存)
3.自动触发:每次关闭redis也会自动触发RDB(shutdown save保存、shutdown save save保存、shutdown nosave 不保存)
4.自动触发:执行flushall命令也会自动触发RDB(是save保存方式)
配置:
1.设置rdb保存条件: redis.conf save 900 1(至少900秒是否有一次操作)
2.保存到的文件:redis.conf **dbfilename
手动保存命令:
1.save (当前进程来执行保存操作,在保存时将不能写入数据)
2.bgsave(redis开启fork子进程,操作时可以写入操作)
2.【aof】(aof开启自动替换rdb,之前rdb存储的数据将不能查询)
优点:
1.安全性高,保存频繁,追加保存
2.恢复快
缺点:
1.性能低,一直在做保存操作
2.保存的文件体积大(可以通过bgrewriteaof命令优化aof文件体积)
配置:
1.开启aof: redis.conf appendonly yes
2.保存到的文件:redis.conf appendfilename “appendonly.aof”
3.触发时机:appendfsync always(每次修改) appendfsync everysec(每秒修改)
4.自动优化aof文件(按照优化后的aof文件大小来计算下一次的优化条件):redis.conf auto-aof-rewrite-percentage 100(百分百) ---- auto-aof-rewrite-min-size 64mb(aof文件大小)
手动优化命令:bgrewriteaof
重写aof文件内容(把Redis进程内的数据转化为写命令同步到新AOF文件中):
1. 进程内过期的数据不用在写入
2. 旧AOF文件含有的无效命令 del k1, set a 1, set a
3. 多条命令可以合并为一个命令,为了防止单个命令过大造成客户端缓冲区溢出,对于list,set,hash,zset 等类型的操作,以64个元素为界拆分为多条。
2.【rdb、aof混合模式】(reids 4.0版本之后才可以混合模式)
优点:
1.保存为aof的保存方式
2.存储时,先存储aof格式,通过优化将之前存储的aof数据转换为rdb数据
配置:
1.开启混合模式: redis.conf appendonly yes — aof-use-rdb-preamble yes
手动优化命令:bgrewriteaof
在保存文件一般时宕机,redis拒接接受这个文件:redis-check-aof
缓存三种问题:
在缓存时常见的三大问题,及解决方案
- 缓存穿透
- 缓存击穿
- 缓存雪崩
- 缓存宕机
1.【缓存穿透】
含义: 查询数据库一定没有的数据,推论:redis肯定没有,结论:每一次请求都会发到数据库
解决方法: 将null缓存(key重复请求次数高,选择这个)(问题:1.大量的缓存会占用内存,对null key设置短的过期时间;缓存与数据库不一致,再数据库修改时,修改缓存里的值)、布隆过滤器(key重复请求次数低,选择这个)(具体使用,见同级文档)
2.【缓存击穿】
含义: 失效的瞬间(单个数据)大量用户访问:在第一次返回之前,大量用户访问
解决方法: 使用互斥锁、永不失效
3.【缓存雪崩】
含义: 缓存在同一时间大面积失效(多条数据)
解决方法: 缓存时间相同的,失效的时间也是相同的–>缓存多个key的时候,把时间错开 、不失效
4.【缓存宕机】
含义: 缓存再宕机后,大量请求涌入数据库
解决方法: 缓存集群部署、使用Hystrix
内存过期策略(redis采用的是惰性删除+定时删除)
在添加redis数据时,当数据过期时,数据的删除时机
- 惰性删除
- 定时删除
- 定期删除
1.【惰性删除】
含义: 在获取key时,redis检测key是否过期,如果过期redis会进行删除,并且不会返回数据
优点: 只删除当前key,CPU占用时间时比较少的,删除操作也是到了最后时刻
缺点: 大量过期key,很长一段时间无人获取,导致无用垃圾占用大量内存
2.【定时删除】
含义: 在为key设置过期时间时,会为key创建一个定时器,让定时器在key的过期时间到了时,立刻删除key
优点: 实时删除过期key,保证内存尽快释放
缺点: 创建大量定时器会严重消耗性能;若过期key很多,频繁进行删除操作,会大量占用CPU使用时间
3.【定期删除】
含义: redis定期随机抓取设置了过期时间的key,来检查和删除key(并非检查全部key,这样CPU负载会很高),如果抽取的key的过期比例超过 1/4,就继续抽样和删除
优点: 通过定期删除,减少删除操作对CPU时间的占用
缺点: 对于没有抓取到已经过期的key来说,依然占用着内存
如何配置?
redis.conf 的hz选项,默认为10 (即1秒执行10次,100ms一次,值越大说明刷新频率越快,最Redis性能损耗也越大)
内存淘汰策略
Redis 在使用的内存空间超过 maxmemory 值时的数据淘汰策略,默认 maxmemory 为0,没有限制。32bit操作系统 maxmemory 默认为3GB。
- noeviction(默认): 禁止驱逐数据,新写入操作会报错
- allkeys-lru: 从数据集中挑选最久使用的数据淘汰
- allkeys-random: 从数据集中任意选择数据淘汰
- allkeys-lfu: 从所有数据中,挑选最少使用的
- volatile-lru: 从设置了过期时间的数据集,挑选最久使用的数据淘汰
- volatile-random: 从设置了过期时间的数据集,任意选择数据淘汰
- volatile-ttl: 从设置了过期时间的数据集,挑选即将过期的数据淘汰
- volatile-lfu: 从设置了过期时间的数据集,挑选最少使用的
如何配置?
rediswindows.conf文件配置,maxmemory-policy noeviction
redis事物
redis事物不支持事物回滚,不保证原子性,没有隔离级别的概念
Redis只能保证一个client发起的事务中的命令可以连续的执行,而中间不会插入其他client的命令
- watch 监控一个或多个key
- unwatch 取消watch对所有key的监视
- multi 开启事物
- exec 提交事物
- discard 取消提交事物
1.【watch】
说明::在事物之前watch一个key,这个key在事物提交前,如果key发生改变,那事物将提交失败,否则成功(watch实际上用的是版本号乐观锁概念,一旦key有变动,版本号+1)
注意:
1.事物开启之后,输入无效命令,提交事物后,都不会执行成功
2.事物开启之后,输入语法性命令(类似java 1/0),提交事物,其他命令执行成功,只有那条命令会执行错误
redis通讯模式
redis集群模式
- 主从模式
- 哨兵模式
- redis-cluster模式
1.【主从模式】
优点:
1.主从复制:写入master的数据会同步到slave(提高了数据可靠性)
2.读写分离:master可以读写,slave只能读(提高了性能)
缺点:
1.没有解决单点失效(如果主节点宕机,那就无法写入)
2.没有解决高可用性
命令:
1.查看从节点信息:info replication
2.客户端连接服务时输入密码(服务没有设置就不需要输入):auth <password>
配置:
1.配置主服务密码:masterauth <password>
2.设置自己节点的密码:requirepass <password>
节点数据的持久化:
1.每一个节点(主节点、从节点)的持久化数据方式都按各自节点的配置来走
数据同步流程:
1.从节点和主节点第一次连接,会全量同步(从节点会持久化全量同步数据)
2.之后主节点变动的数据,以增量的方式同步(持久化方式按节点配置来走)
如何配置?(配从不配主):
1.redis.conf:slaveof <masterip> <masterport>(5.0之前的版本)
2.redis.conf:replicaof <masterip> <masterport>(5.0之后的版本)
2.保证redis集群端口号不同
2.【哨兵模式】
优点: 在主从模式的基础上解决了单点失效,master异常关闭后,由哨兵自动选取slave做master
概念: 客观下线 主观下线
如何配置?
1.在redis目录下创建一个sentinel.conf文件,文件内容:
#当前Sentinel服务运行的端口
port 26379
#master
#Sentinel去监视一个名为mymaster的主redis实例,这个主实例的IP地址为本机地址127.0.0.1,端口号为6379,
#而将这个主实例判断为失效至少需要2个 Sentinel进程的同意,只要同意Sentinel的数量不达标,自动failover就不会执行
sentinel myid 44ec7f4a55ebd12cad9717b35065e7e058aac955
#指定了Sentinel认为Redis实例已经失效所需的毫秒数。当 实例超过该时间没有返回PING,或者直接返回错误,那么Sentinel将这个实例标记为主观下线。
#只有一个 Sentinel进程将实例标记为主观下线并不一定会引起实例的自动故障迁移:只有在足够数量的Sentinel都将一个实例标记为主观下线之后,实例才会被标记为客观下线,这时自动故障迁移才会执行
sentinel monitor mymaster 127.0.0.1 6380 2
#指定了在执行故障转移时,最多可以有多少个从Redis实例在同步新的主实例,在从Redis实例较多的情况下这个数字越小,同步的时间越长,完成故障转移所需的时间就越长
sentinel down-after-milliseconds mymaster 5000
#如果在该时间(ms)内未能完成failover操作,则认为该failover失败
sentinel config-epoch mymaster 16
# Generated by CONFIG REWRITE
dir "D:\\AboutJava\\redis\\cluster\\master6379"
sentinel leader-epoch mymaster 16
sentinel known-slave mymaster 127.0.0.1 6379
sentinel known-slave mymaster 127.0.0.1 6381
sentinel known-sentinel mymaster 127.0.0.1 26381 fc9f76a576e42d28883a7dfc3650ccaf25e4307f
sentinel known-sentinel mymaster 127.0.0.1 26380 322b80be6353d0fe6b90fadbf765aa73567228d1
sentinel current-epoch 16
2.创建start_sentinel.bat批处理文件,文件内容:
redis-server.exe sentinel.conf --sentinel
3.运行时两个批处理文件都运行
3.【redis-cluster模式】(redis 5.0)
优点:
1.解决了redis内存不够用问题,通过多个master来增大redis集群内存
2.master之间相互通讯,相互选举,保证故障转移
3.主从复制,master的从节点同步主节点数据,不做读写操作,作为master的备用节点,master宕机后由他的从节点顶替master
数据存储方式:
1.有几个master节点,就将16383个哈希槽平均分配
2.用CRC16计算出key的哈希值,%16383,的到的数分配到不懂的节点中
如何配置?
1.redis.conf
1.cluster-enabled yes
2.cluster-config-file nodes-6380.conf
3.cluster-node-timeout 15000
2.保证redis集群端口号不一致
3.在随便一个redis目录下cmd,输入命令:
redis-cli --cluster create 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384 127.0.0.1:6385 --cluster-replicas 1