redis的跳表

skiplist 少听到,从他来拓展一下。

zset 使用的数据结构,大概长这样, 

显而易见,他比链表查询速度快。 node 节点大概长这样。 

typedef struct zskiplistNode {
    // 成员(Member)
    sds ele;  // SDS 是 Redis 的字符串类型
    // 分值(Score)
    double score;
    // 多级指针(Forward)
    struct zskiplistNode **backward;  // 反向指针(可选,用于双向遍历)
    struct zskiplistLevel {
        struct zskiplistNode *forward;  // 指向下一节点
        unsigned int span;             // 跨度(可选,用于计算排名)
    } level[];  // 柔性数组,层数可变
} zskiplistNode;
 
typedef struct zskiplist {
    struct zskiplistNode *header, *tail;  // 头节点和尾节点
    unsigned long length;                 // 节点数量
    int level;                            // 当前最大层数
} zskiplist;

一个数据的sds 可能存在与skiplist 的多层list 上; 插入数据时 node 中的level决定了该节点存在与哪些层的list 上。  删除时逐层删除该层list 上的节点, 调整前后节点的 双向指针。 他不需要保持树高度平衡, 没了AVL, 节省性能啊

拓展一下: 

SDS: redis 自己实现的string , 拓展了c的string 去掉了c中结尾的“\0”

ziplist: redis 中的压缩链表, 它里面的node 叫做entry , 每个entry 记录自己的长度,entry里没有前后节点指针, 即所谓压缩。entry 中记录了前一个节点的长度, 从而实现了遍历, 前向 next =curr+pre_len; 后向 next = curr -pre_len 

锁: set nx ex 设置锁 ,秒杀抢购锁住库存, 在锁的时候加上自己的uuid, 只能解自己uuid的锁;  redis 默认只写到master 节点, 如果此时down机 那么 slave 没同步会导致锁不住,那么对所有节点检查写入成功,redlock组件干的事了。

zset 实现排行榜,  时间戳 滑动窗口限流,姓名排序,电话排序,电话簿,好友列表

incr, decr 发号 计数

list 消息队列

持久化:  AOF  和 RDB  ; rdb 用于主从复制,备份恢复等,save 60 1000 60s 内写1000次哪怕是同一个 调用bgsave非阻塞写。 AOF append only file ,有always,everysec 和 no ; 对比下 innodb wal 的三种刷盘策略 : 1 每个trx提交写log,2每个trx提交写 page cache , 0 每个trx 提交写 redo log buffer ;混合持久化,触发aof时写格式变成二进制,否则为aof的日志;

redis 与mysql: 先写redis 再删redis; 若先删redis 则延迟双删;保证最终一致性。

热key : 单key缓存失效时击穿, 用双重检查锁,在key过期时加锁处理

雪崩:多key集中过期雪崩,多key失效时间随机,或预热。

穿透:redis 和 sql都不存在,大量请求到db,那让redis 缓存下不存在的,

bitmap: 用到签到,打卡场景不错

set : 共同好友 ;大量数据的时候  用neo4j 或布隆过滤器; 抽奖人,

大key :超过xx量认为是大key,拆分大key或者开启惰性删除,不开的话删除会阻塞,别用keys 获取了,用scan 扫

惰性删除: 过期了不会立即删,下次被访问时再删。

定期删除: 100ms随机抽取部分设置了过期时间的key,删除其中的过期的key;用unlink交给异步删比del删不阻塞主线程;

主动清理: 内存使用超过maxmemory 触发; 清理设置了过期时间的 ; 清理所有键;不清理的话写OOM读没问题; rand,lru,lfu ,ttl 三种清理策略

lru: 最近一段时间内的访问次数, 可能干掉这段时间前的热key,  

lfu:  访问次数, 历史访问的热key 可能一直留着, 需要基于时间给次数做衰减 从而干掉冷数据

与memcached区别: mem 无持久化,支持的数据类型少。

单线程处理读写,多线程处理异步io:epoll 多路复用所以能单线程到10wqps;开多个节点利用机器CPU;

可用性架构:单主从切换时需要介入,哨兵单主了同步会慢,而且主挂哨兵选主的时间内会访问失败,集群是多主从了,相当于一主分片到了多主,并发高了,出问题的概率小了

集群分片: crc(key) mod 16384 = slot , 看slot 配置在哪个主

 object encoding key 查看底层数据结构

127.0.0.1:6379> SET mykey "hello"
OK
127.0.0.1:6379> OBJECT ENCODING mykey
"embstr"
127.0.0.1:6379> LPUSH mylist 1 2 3
(integer) 3
127.0.0.1:6379> OBJECT ENCODING mylist
"quicklist"
127.0.0.1:6379> ZADD myzset 1 "one" 2 "two" 3 "three"
(integer) 3
127.0.0.1:6379> OBJECT ENCODING myzset
"skiplist"

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值