zoukankan      html  css  js  c++  java
  • redis深度历险-读书笔记

    redis数据结构

    • string
      采取分配冗余空间的方式减少内存频繁分配
      当字符串长度少于1MB,扩容都是成倍扩展
      当字符串长度大于1MB,每次只会多扩1MB
      字符串长度最大为512MB
      字符串由多个字节组成,每个字节由8bit组成,就是bitmap(位图)数据结构

    • list
      相当于java中的LinkedList
      redis底层存储的是quicklist 快速链表
      数据量少的时候是ziplist,数据量大的时候改成quicklist
      quicklist就是多个ziplist连在一起

    • hash
      redis的hash只能是字符串,
      rehash是渐进式rehash
      在渐进式rehash时,会保留新旧两个hash结构,查询会同时查询两个hash结构,然后在定时任务中渐渐将旧的结构的数据迁移到新的结构

    • set
      低层是hashset

    • zset
      类似于java的soreset和hashmap的结合体

    分布式锁

    分布式锁需要设置和超时为原子命令
    set a a expire 5 nx
    超时问题:如果加锁和释放锁之间逻辑执行太长,超出了锁的超时限制,建议分布式锁下的程序执行时间尽量短
    解决办法:将set的value设置成随机值,避免别的线程将自己的锁释放,确保当前线程占有的锁不会被其他线程释放掉
    除非这个锁是因为到期了而被释放

    • 可重入性
      如果一个锁支持同一个线程同时加锁,那么这个锁就是可重入的
      如果redis要支持可重入锁,需要对客户端的set方法进行包装,使用ThreadLocal变量存储当前持有锁的计数
      尽量避免使用可重入锁

    延时队列

    实现阻塞队列: 使用blpop和brpop取出数据,没有数据的时候阻塞
    队列空了:可以使用阻塞指令,但是要注意超时的情况, 可以使用轮询的方式,比较耗性能,可以加sleep让cpu降下来

    分布式锁冲突处理: 1.直接抛异常 2.sleep后重试 3.将请求转移到延迟队列,稍后重试

    延时队列: 通过zset有序列表实现,将消息序列化成zset的value,到期时间设置为score,然后用多个线程轮询到期的任务

    位图

    用于用户签到类业务,365天只需要365bit
    位图的数组是自动扩展的,如果设置的某个偏移位超出了现有内容范围,则自动将数组进行零扩充
    setbit s 1 1
    getbit s 1

    Scan

    因为keys * 容易导致阻塞,所以用scan替代keys
    scan 0 match a* count 1000

    大key扫描

    如果key太大,会导致数据迁移卡顿
    如果需要扩容的时候,会一次性申请一块大的内存,会导致卡顿,
    如果key被删除,会一次性回收一块大的内存,也会导致卡顿

    • 扫描大key

    redis单线程

    1.基于内存
    2.多路复用:select系列事件轮询api,非阻塞io

    • 指令队列:客户端指令通过队列顺序处理
    • 响应队列
    • 定时任务

    redis持久化

    使用操作系统的多进程Copy On Write机制进行
    RDB: fork一个子进程做持久化,当父进程修改数据,会先拷贝一份出来修改
    所以在子进程建立后,数据是不会变化的
    AOF: redis会先执行指令再保存日志
    AOF重写: 开辟一个子进程对内存遍历,转换成一系列redis操作指令,序列化到一个新的AOF日志文件,序列化完成后,再将增量AOF日志追加,完成后替换旧的AOF文件

    • redis4.0增加混合持久化,重启的时候先加载rdb的内容,然后再加载aof日志,代替了之前的AOF全量文件重放

    redis集群

    redis主从同步是异步的,不满足一致性
    主节点修改数据后会立即返回,从节点会尽量追赶主节点,redis保证数据最终一致性

    • 增量同步
      主节点将指令记录在本地的buffer中,然后异步将buffer同步到从节点
      从节点一边执行同步指令流,一边向主节点反馈自己同步到哪里了
    • 快照同步
      首先在主节点执行一次bgsave
      将当前内存数据全部都保存到磁盘文件中
      再将快照传到从节点
      从节点加载完成后再通知主节点进行增量同步

    sentinel(哨兵)

    当主节点挂掉,会选一个最优从节点变成主节点
    客户端先连接sentinel,通过sentinel查询主节点的地址,然后和主节点进行数据交互
    当主节点发生故障,客户端会向哨兵重新获取主节点地址

    codis


    codis默认将所有key划分为1024个槽位,首先对客户端传过来的key进行crc32运算计算hash值,再将hash后的整数值对1024取余就是槽位

    • 自动迁移:
      增加新的redis实例后,遍历指定slot下所有key,Codis通过SLOTSSCAN扫描出待迁移槽位所有key,然后挨个迁移每个key到新的redis节点

    • 自动均衡
      在系统空闲的时候观察每个redis实例对应的slot数量,如果不平衡会自动进行迁移

    • codis集群配置中心使用zookeeper

    • 执行mget

    redis cluster

    redis cluster由最少3个节点组成
    每个节点负责一部分数据
    三个节点连接成对等的集群
    一共分成16384个槽
    Redis集群,要保证16384个槽对应的node都正常工作,如果某个node发生故障,那它负责的slots也就失效,整个集群将不能工作。
    为了增加集群的可访问性,官方推荐的方案是将node配置成主从结构,即一个master主节点,挂n个slave从节点。这时,如果主节点失效,Redis Cluster会根据选举算法从slave节点中选择一个上升为主节点,整个集群继续对外提供服务,Redis Cluster本身提供了故障转移容错的能力。

    从节点过期策略

    从节点不会进行定期扫描,从节点对过期处理是被动的
    主节点在key过期后会在AOF写入一个del命令,然后同步到从节点

    字符串

    字符串叫sds
    sds结构:

    长度短时,用embstr存储
    长度超过44字节,用raw形式存储

    list

    单个ziplist为8kb,如果超出会新建一个ziplist

  • 相关阅读:
    VirtualBox设置共享文件夹失败的解决方法
    内存泄漏
    javascript语言精粹学习记录一
    javascript之继承
    HadoopFSDataset
    linux eclipse启动问题及解决方法
    css规范总结
    pycharm
    第十章 call和ret指令
    第五章 [bx]和loop指令
  • 原文地址:https://www.cnblogs.com/Baronboy/p/15184463.html
Copyright © 2011-2022 走看看