Redis基础2
三种特殊的类型
geospatial地理位置
- 推算两地之间的距离
- geo的底层原理就是Zset
1 | #添加地理位置geoadd |
Hyperloglog数据结构
- 基数:不重复的元素
- Redis Hyperloglog基数统计的算法,网页UV:一个网页同一个人访问多次算作是一个人,不会重复统计
- 传统方式,set保存用户ID,set中不允许重复,可以使用set中元素的数量作为标准
- 目的是为了计数,不是为了保护用户ID,需要login呢?
- Redis Hyperloglog基数统计的算法占用12KB内存,如果从内存角度来比较,是首选,错误率0.81%,统计UV任务
1 | 127.0.0.1:6379> pfadd mykey a b c hc o j k k k k hy ii o p p g f u #添加 |
Bitmaps位图
- 位存储,只有0和1的两种状态
- 用户活跃/不活跃 登录/未登录 打卡/未打卡都可以使用Bitmaps
- 只要46个字节就可以存储用户一年内的状态
1 |
|
事务
- Redis事务的本质,一组命令的集合,一个事务中的所有命令都会被序列化,在事务执行过程中会按照顺序执行。
- 一次性
- 顺序性
- 排他性
- 所有命令在事务中并没有直接被执行,只有发起执行命令才会被执行
- Redis单条命令保存原子性,但是是事务不保证原子性
- Redis没有隔离级别的概念
- Redis事务,批量执行命令
- 开启事务 mutli
- 命令入队
- 执行事务 exec
1
2
3
4
5
6
7
8
9127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k4 v4
QUEUED
127.0.0.1:6379> set k5 v5
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
- 放弃事务 discard
- 编译型错误,代码有问题,事务中的所有命令都不会背执行
- 运行时异常,队列中存在语法错误,执行命令时,错误命令抛出异常,其他命令正常执行,(验证了Redis不存在事务原子性)
悲观锁和乐观锁
悲观锁
- 无论做什么都要加锁
乐观锁
- 监视
watch
即为乐观锁,如果监视的值在执行时未发生变化,则执行成功,否则整个队列执行失败
配置文件redis.conf
bind 127.0.0.1
绑定ipprotected-mode yes
保护模式port 6379
端口设置daemonize yes
默认no,yes时以守护进行的方式运行- 持久化:在规定时间内执行了多少次操作,会持续化到文件.rdb .aof
save 900 1
900秒内,至少有一个key进行了修改,即进行持久化操作save 300 10
300秒内至少有10个key进行了修改stop-writes-on-bgsave-error yes
持久化如果出错是否继续工作rbdcompression yes
是否压缩rdb文件,需要消耗一些CPU资源rdbchecksum yes
保存rbd文件时,检查校验错误dir ./
rdb保存的目录
- security安全配置,默认没有密码
config get requirepass
获取密码config set requirepass "111"
设置密码auth 111
获取权限
- 限制client
maxclier 10000
设置能连接上redis的最大服务器数量maxmemory <byte>
Redis配置最大的内存容量maxmemory-policy noeviction
内存到达上限后的处理策略- noeviction:当内存使用达到阈值的时候,所有引起申请内存的命令会报错
- allkeys-lru:在所有键中采用lru算法删除键,直到腾出足够内存为止
- volatile-lru:在设置了过期时间的键中采用lru算法删除键,直到腾出足够内存为止
- allkeys-random:在所有键中采用随机删除键,直到腾出足够内存为止
- volatile-random:在设置了过期时间的键中随机删除键,直到腾出足够内存为止
- volatile-ttl:在设置了过期时间的键空间中,具有更早过期时间的key优先移除
appendonly no
默认不开启aof模式,默认使用rbd方式持久化appendfsync always/everysec/no
每次次该都会同步/每秒执行一次sync/不执行sync
Redis持久化
- 单独创建一个子进程来进行持久化,将数据写入到一个临时文件中,持久化过程结束后将这个文件替换上次持久化后的文件,整个过程主进程不进行任何IO操作。
- 默认使用rdb实现持久化,保存的文件尾dump.rdb,在snapshot中配置
- save命令,flushall,关闭Redis都会生成rdb
- 恢复rdb,dump.rdb在redis-server同级目录下,开启Redis会自动恢复数据
- 适合大规模的数据恢复
- AOF将所有命令保存在一个文件中,恢复的时候就把这些操作全部重新执行一遍,数据量较大时效率较低
appendonly yes
修改配置文件,开启aof- 如果aof文件被破坏,Redis连接失败,
redis-check-aof --fix appendonly.aof
文件恢复aof文件 - 每一次修改都同步,保障文件完整性
- aof修复速度远大于rdb,运行效率也较低
- aof文件默认最大64M,超过这个大小时候fork一个新的进程来重新aof
- 如果redis做缓存,不需要持久化
- 同时开启两种方式,优先使用aof来恢复,aof更加完整
- rdb更适用于备份数据库
Redis发布和订阅
- 用C中的pubsub.c文件,通过publish/subscribe/psubscribe实现订阅和发布的功能
- 订阅频道后,在redis-server中维护一个字典表,字典表标识频道,字典的值是链表,链表中保存所有订阅这个频道的客户端
- subscribe命令将客户端添加到给定的channel的订阅链表中
- publish命令遍历链表,将消息发送给所有订阅者
Redis主从复制
- 将一台Redis服务器的数据复制到其他服务器,称为主节点和从节点,数据复制是单项的,从主复制到从,主节点只能有一个。一般为一主二从
- 读写分离,80%的情况下都在进行读操作,减缓服务器压力
- 主从复制的作用:
- 数据冗余:实现数据的热备份
- 故障恢复:主节点出现问题时可以由从节点恢复
- 负载均衡:主从复制配合读写分离,分担服务器负载,在写少读多的情况下,可以大大减少Redis服务器的并发量
- 高可用(基群)基石:主从复制是哨兵和基群能够实施的基础
- 环境配置:
- 默认所有节点都是主节点,因此需要配置从库
- 复制多个redis.conf,修改配置文件,所有服务的pid、dump.rdb、端口、logfile等不能重复
slaveof 127.0.0.1 6379
配置主节点,此节点变为从节点info replication
查看信息- 真实的主从配置,在文件中配置,则是永久的
- 主机中的所有信息都会被从机自动保存
- 主机断开连接,重新连接成功后,能立即重新读取数据。实际应该在从机中选取一个作为主机
slaveof no one
将自己设置为主节点,此时可以手动将其他从节点配置到当前主节点上- 若是从机断开,重新启动后数据立马从主机中再次获取(永久的主从配置)
- 复制原理:
- slave启动成功连接到master后发送一个sync同步命令
- master接到命令后启动后台存盘过程,同时收集所有用于修改数据集命令,在后台进程执行完毕后,master将传送整个数据文件到slave,并完成一个完全同步
- 全量复制:slave服务器在接收到数据库文件数据后,将其存盘并加载到内存中
- 增量复制:master继续将新的所有收集到的修改命令一次传递给slave,完成同步
- 只要重新连接master,一次完全同步将会被自动执行,即全量复制
哨兵模式
- 重新开启一个进程,作为一个独立的进程,发送命令,等待Redis服务器相应,监视多个Redis服务器
- 专业套娃:配置多个哨兵互相监督
- 检测到主节点不可用,哨兵之前投票,确定宕机后,进行failover操作。切换成功后,通过发布订阅模式,将哨兵把自己的监控转移到新的主机
sentinel.conf,
redis-sentinel sentinel.conf
启动哨兵模式1
2
3
4sentinel monitor myredis 127.0.0.1 6379 1 //被监控的名称,1代表主机挂了之后投票,1票就可以认为是宕机
sentinel failover-timeout 18000
//默认三分钟原本的主机重新连接,只能归并到现在的主机下面当从机
- 哨兵集群,基于主从复制模式,主从切换转移故障,实现系统的高可用性
- 哨兵模式不好在线扩容,基群到达上线后,很难实现在线扩容,需要单独配置
Redis缓存穿透和雪崩
- 缓存没有命中,持久层数据库也没有,当很多用户都在请求持久层数据库,会给持久层数据库造成很大的压力,相当于就是缓存穿透
- 使用布隆过滤器,对所有可能查询的参数以hash形式存储,在控制层先进行过滤,避免对底层存储系统产生大的查询压力
- 缓存空对象,也会造成一些新的问题
- 缓存击穿:大并发集中对一个点进行访问,这个key在失效的瞬间,持续的大并发就击破缓存,直接请求数据库
- 设置热点数据不过期,加互斥锁,保证每个key同时只有一个线程去持久层数据库查询数据(限流降级)
- 缓存雪崩,在某个时刻,缓存集体失效
- Redis高可用,增设Redis服务器
- 限流降级,缓存失效后通过一定的手段来控制读写数据库写缓存的线程数量
- 数据预热,在正式部署钱对可能的数据线访问一遍,在即将发生大并发访问钱手动触发加载缓存不同的key,设置不同的过期时间,使缓存失效的时间更均匀