redis学习笔记01

redis学习记录

redis特性

  • 简单

    • 不依赖外部库
    • 单线程模型
  • 高可用–》redis-sentinel

  • 分布式 redis-cluster(v3.0)支持分布式

  • redis的典型应用场景

    • 缓存系统
    • 计数器
    • 消息订阅系统
    • 排行榜
    • 社交网络
    • 实时系统
  • redis的三种启动方式

    • 最简启动

    • 配置文件启动

    • 动态参数启动 redis-cli -h 127.0.0.1 -p 6379

    • 验证方式

      • ps -ef|grep redis
      • netstat -antpl |grep redis
      • redis-cli -h ip -p port ping
    • 启动方式比较

      • 生成环境选择配置启动
    • 单机多实例配置文件可以用端口进行区分开

  • 数据结构和内部编码

  • key

    • string
    • 内部编码方式包含
      • raw
      • int
      • embstr
    • hash
    • hashtable
      • ziplist
    • list
    • linkedlist
      • ziplist
    • set
    • hashtable
      • intset
    • zset
    • skiplist
      • ziplist
    • redisObject
  • 数据类型(type)

    • 编码方式(encoding)
    • 数据指针(ptr)
    • 虚拟内存(vm)
    • 其他信息

单线程

  • 纯内存

  • 非阻塞io

  • 避免线程切换和竞态消耗

  • 一次只允许一条命令

  • 拒绝长(慢)命令

    • keys,flushall,flushdb,slow lua script,mutil/exec ,operate big value(colleciton)
  • 慢查询

    • 生命周期
      • 1.发生命令,2.排队,3.执行命令,4.返回结果
      • 慢查询发送在第3个阶段
      • 客户端超时不一定是慢查询,但是慢查询是客户端超时的一个可能因素
    • 两个配置
      • slowlog-max-len
        • x先进先出的队列
        • 固定长度
        • 保存在内存内
      • slowlog-log-slower-than
        • 慢查询阈值(单位:微秒)
        • slowlog-log-slower-than=0,记录所有的命令
        • slowlog-log-slower-than<0,不记录任何命令
        • config get slowlog-max-len=128
        • config get slowlog-log-slower-than=10000
        • 修改配置文件进行重启
        • 可以使用config set进行动态设置
    • 三个命令
      • slowlog get [n] :获取慢查询队列
      • slowlog len:获取慢查询队列长度
    • 运维经验
      • slowlog-max-len不要设置过大,默认10ms,通常设置1ms
      • slowlog-log-slower-than不要设置过小,通常设置在1000左右
      • 理解命令的生命周期
      • 定期持久化慢查询
  • pipeline

    • 什么是流水线
      • 一次网络世界+n次命令时间
      • redis的命令时间是微秒级别的
      • pipeline每次条数要控制
    • 客户端实现
    • 与原生M对比
      • 非原子操作,但是保证顺序
    • 使用建议
      • 注意每次pipeline携带的数据量
      • pipeline每次只能作用在一个redis节点上面
  • 发布订阅

    • 角色
      • publisher
      • subscriber
      • channel
    • 模型
    • api
    • 和消息队列进行对比
  • bitmap

    • 位图
      • 字符串big对应的二进制
    • 相关命令
    • 独立用户统计
  • HyperLogLog

    • 新的数据结构?
      • 基于hyperloglog算法:极小空间完成独立数量统计
      • 本质还是字符串
    • 三个命令
      • pfadd key element[element …] 向hyperloglog添加元素
      • pfcount key[key …]计算hyperloglog的独立总数
      • pfmerge destkey sourcekey[sourcekey …] 合并多个hyperloglog
    • 内存消耗
      • 百万独立用户
    • 使用经验
      • 是否能容忍错误?(错误率:0.81%)
      • 是否需要单条数据
  • geo

    • geo是什么

      • 地理信息定位:存储经纬度,计算两地距离,范围计算等
    • 5个城市经纬度

    • 相关命令

      • geoadd key longtitude latitude memeber[longtitude latitude member …]增加地理信息

      • geopos key member[member…] 获取地理位置信息

      • geodist key member1 member2[unit]

      • 获取两个地理位置的距离unit m(米),km(千米),mi(英里),ft(尺)

      • georadius key longtitude latitude radiusm|km|ft|mi[withcoord][withdist]][withhash]

        [COUNT count] [asc|desc][store key][storedist key]

        • georadiusbymember key member获取指定位置内的地理位置信息集合
    • 相关说明

      • since 3.2+
      • type geoKey =zset
      • 没有删除api:zrem key member
  • 开发运维常见问题

    • fork操作
      • 同步操作
      • 与内存量息息相关:内存越大,耗时越长(与机器类型有关)
      • info:latest_fork_usec
      • 改善fork
        • 优先使用物理机或者高效支持fork操作的虚拟化技术
        • 控制redis实例最大可用内存:maxmemory
        • 合理配置linux内存分配策略:vm.overcommit_memory=1
        • 降低fork频率:例如放宽aof重写自动触发时机,不必要的全量复制
    • 进程外开销和优化
      • cpu
        • 开销:rdb和aof文件生成,属于cpu密集型
        • 优化:不要做cpu绑定,不和cpu密集型部署
      • 内存
        • 开销:fork内存开销,copy-on-write
        • 优化echo never>/sys/kernel/mm/transparent_hugepage/enabled
      • 硬盘
        • 开销:aof和rdb文件的写入,可以结合iostatiotop分析
        • 硬盘优化
        • 不要和高硬盘负载服务部署一起:存储服务,消息队列等
        • no-appendfsync-on-rewrite=yes
        • 根据写入量决定磁盘类型:例如ssd
        • 单机多实例持久化文件目录可以考虑分盘
    • aof追加阻塞
      • aof阻塞定位
      • info persistence
    • 单机多实例部署
  • redis复制的原理与优化

    • 什么是主从配置

      • 单机存在的问题 机器故障 容量瓶颈 qps瓶颈
      • 数据副本
      • 扩展读的性能
    • 复制的配置

      • slaveof no one
      • slaveof ip port
      • slave-read-only yes
    • 全量复制和部分复制

      • psync ? -1

      • +fullresync {runid}{offset}

      • save masterInfo

      • bgsave

      • sendrdb

      • sendbuffer

      • flush old db

      • flush db

      • 全量复制开销

        • bgsave时间
        • rdb网络传输时间
        • 从节点清空数据时间
        • 从节点加载rdb时间
        • 可能的aof重写时间
      • 部分复制

    • 故障处理

      • 无自动故障转移
    • 开发运维常见问题

      • 读写分离
        • 读写分离:读流量分摊到从节点
        • 可能遇到的问题:
          • 复制数据延迟
          • 读到过期的数据
          • 从节点故障
      • 主从配置不一致
        • 例如maxmemeory不一致:丢失数据
        • 例如结构化优化参数(例如:hash-max-ziplist-entries):内存不一致
      • 规避全量复制
        • 第一次全量复制 不可避免
          • 小节点 ,低峰
        • 节点运行id不匹配
          • 主节点重启(运行id变化)
        • 复制积压缓冲区不足
          • 网络中断,部分复制无法满足需求
          • 增大复制缓冲区配置rel_backlog_size,网络“增强”
      • 规避复制风暴
        • 单节点复制风暴
          • 问题:主节点重启,多从节点复制
          • 解决:更换复制拓扑
        • 单机器复制风暴
          • 机器宕机后,大量全量复制
          • 主节点分散多台机器
  • 哨兵 redis-sentinel

    • 主从复制高可用?
    • redis sentinel故障转移
      • 多个sentinel发现并确认master有问题
    • 选举储一个sentinel作为领导
      • 选出一个slave作为master
    • 通知其余slave成为新的master的slave
      • 通知客户端主从变化
    • 等待老的master复活成为新的master的slave
  • 架构说明

    • 安装配置

      • 配置开启主从节点

      • 配置开启sentinel的监控主节点(sentinel是特殊的redis) 默认26379

      • 实际应该多机器

      • 详细配置节点

        • port ${
                      
                      port}
          dir "/opt/soft/redis/data/"
          logfile "${port}.log"
          daemonize yes
          sentinel monitor mymaster 127.0.0.1 7000 2
          sentinel down-after-milliseconds mymaster 30000
          sentinel parallel-syncs mymaster 1
          sentinel failover-timeout mymaster 180000
          
      • runId

        • ./redis-cli -p 6379 info server |grep run
      • 偏移量

        • ./redis-cli -p 6370 info replication
    • 客户端连接

      • sentinel节点集合+masterName redis节点变化的通知

      • 客户端从sentinel获取master信息

      • 接入流程

        • sentinel地址集合
        • mastername
        • 不是代理模式
      • jedis

        ​ JedisSentinelPool sentinelPool =new JedisSentinelPool(masterName,sentinelSet,poolConfig,timeout);

        jedis=redisSentinelPool.getResource();最后记得jedis.close()

    • 实现原理

      • 客户端高可用观察
      • 服务端日志分析:数据节点和sentinel节点
    • 常见开发运维问题

      • 节点运维

        • 节点上线和下线

          • 主节点

            • sentinel fialover 手动故障转移
          • 从节点

            • 临时下线还是永久下线,例如是否做一些清理工作,但是要考虑读写分离的情况
          • sentinel节点

          • 节点上线

            • sentinel failover 进行替换
          • 从节点

            • slaveof即可,sentinel节点可以感知
          • sentinel节点

            • 参考其他sentinel节点启动即可
        • 机器下线:例如过保等情况

        • 机器性能不足:例如:cpu,内存,硬盘,网络等

        • 节点自身故障:例如服务不稳定等

      • 高可用读写分离

      s

案例

  • 使用set和bitmap

    • 数据类型 每个userid占用的空间 需要存储的用户量 全部内存量
      set 32位(假设userid是整型,实际很多网站用的是长整型) 50,000,000 32*50,000,000=200mb
      bitmap 1位 100,000,000 12.5mb
  • 1亿用户,5千万独立

  • 使用经验

    • type=string,最大512mb
    • 注意setbit时的偏移量,可能有较大的耗时
    • 位图不是绝对好

    redis 过期策略是:定期删除+惰性删除。
    所谓定期删除,指的是 redis 默认是每隔 100ms 就随机抽取一些设置了过期时间的 key,检查其是否过期,如果过期就删除。
    假设 redis 里放了 10w 个 key,都设置了过期时间,你每隔几百毫秒,就检查 10w 个 key,那 redis 基本上就死了,cpu 负载会很高的,消耗在你的检查过期 key 上了。注意,这里可不是每隔 100ms 就遍历所有的设置过期时间的 key,那样就是一场性能上的灾难。实际上 redis 是每隔 100ms 随机抽取一些 key 来检查和删除的。

    但是问题是,定期删除可能会导致很多过期 key 到了时间并没有被删除掉,那咋整呢?所以就是惰性删除了。这就是说,在你获取某个 key 的时候,redis 会检查一下 ,这个 key 如果设置了过期时间那么是否过期了?如果过期了此时就会删除,不会给你返回任何东西。
    获取 key 的时候,如果此时 key 已经过期,就删除,不会返回任何东西。
    但是实际上这还是有问题的,如果定期删除漏掉了很多过期 key,然后你也没及时去查,也就没走惰性删除,此时会怎么样?如果大量过期 key 堆积在内存里,导致 redis 内存块耗尽了,咋整?
    答案是:走内存淘汰机制。

    内存淘汰机制
    redis 内存淘汰机制有以下几个:
    • noeviction: 当内存不足以容纳新写入数据时,新写入操作会报错,这个一般没人用吧,实在是太恶心了。
    • allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 key(这个是最常用的)。
    • allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个 key,这个一般没人用吧,为啥要随机,肯定是把最近最少使用的 key 给干掉啊。
    • volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的 key(这个一般不太合适)。
    • volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个 key。
    • volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的 key 优先移除。

猜你喜欢

转载自blog.csdn.net/hbn1326317071/article/details/100549410
今日推荐