A collection of 12 posts

redis高性能概述

背景 今天来讲一下redis高性能的原因,如何以单线程来支撑10W级别的并发。 Redis的事件循环 C10K problen C10K就是单机一万并发的问题,最初服务器是来一个连接就创建一个进程/线程,这样在并发量多的情况下就会有性能问题。 问题描述 创建的进程/线程多了,数据拷贝频繁 缓存I/O需要数据拷贝,其拷贝流程是:磁盘 -> ...

redis的几个数据结构——quicklist

背景 redis的内存管理以追求极致著称,我们来看看它怎么管理容易产生内存碎片的链表。 双向链表 双向链表便于在表的两端进行push和pop操作,但是它的内存开销比较大。首先,它在每个节点上除了要保存数据之外,还要额外保存两个指针;其次,双向链表的各个节点是单独的内存块,地址不连续,节点多了容易产生内存碎片。 ziplist ziplist由于是一整块连续内存,所以存储效率很高。但是,它不利于修改操作,每次数据变动都会引发一次内存的realloc。特别是当ziplist长度很长的时候, ...

redis的几个数据结构——ziplist

背景 ziplist是列表、hash和zset元素较少时的存储格式: hash: 当哈希类型元素个数小于hash-max-ziplist-entries配置(默认512个); 所有值小于hash-max-ziplist-value配置(默认64个字节); sorted set: 元素个数小于zset-max-ziplist-entries配置,默认128; 所有值小于zset-max-ziplist-value配置,默认64。 实现 如下图所示,zlist由下面几个元素组成: zlbytes :字节长度,4个字节 ...

redis的几个数据结构——RedisObject

RedisObject是redis类型的核心,每个键值和参数都表示为RedisObject: typedef struct redisObject { // 类型 unsigned type:4; // 编码 unsigned encoding:4; // 对象最后一次被访问的时间,缓存淘汰使用 //使用LRU算法时存储的是对象访问时间,使用LFU算法时存储的是上次访问时间与访问次数 //LRU:unsigned的低24 bits的lru记录了redisObj的LRU ...

redis的几个数据结构 —— HyperLogLog

HyperLogLog 应用场景 在工作中经常会有uv、pv的统计,传统的实现方式就是用户日志上报到hbase,然后通过hive来查询,每日出报表。 如果是使用redis来实现,假设是使用ip来区分用户,假设存储一个ip为15个字节,300万的ip其开销是45MB,唯一ip可能每天出现数十万、数百万甚至数千万。 在redis中,有一种基于概率算法的计算集合的基数的数据结构,就是HyperLogLog,可以解决不要求百分百精度的UV计算。在上面例子中的300万ip,使用HyperLogLog只需要12字节即可计算。 UV ...

redis的几个数据结构 —— LFU

LFU 在有内存限制,需要淘汰冷数据的系统中,需要有算法来算出哪些数据算是冷数据。最常见的就是LRU,最近最少使用。但是LRU有一定的缺陷,如果有个冷数据忽然被访问,则会被提到列表最前,这样子可能会导致真正的热数据被清理掉。 假设有以下数据访问:横轴是时间线,纵轴是同一个时间点。 ~~~~~A~~~~~A~~~~~A~~~~A~~~~~A~~~~~A~~| ~~B~ ...

redis的几个数据结构 —— zset

zset实现和解析 zset是redis中比较经典的数据结构了,有序集合,带分值可排序,有序集合的硬性需求有这两条: 分值区间获取key 通过key直接获取分值 而redis中zset其各个操作的时间复杂度如下: 获取分值:O(1) 添加元素:O(M*log(N)), N 是有序集的基数, M 为成功添加的新成员的数量 ...

redis的几个数据结构 —— scan

背景 今年上半年看了redis的源码,做了两次分享,一直没有更新到blog上,趁着过年整理一波。 scan命令实现 禁用keys 通常来说,redis线上环境都会被运维进制使用keys命令,因为这个命令会造成redis阻塞。redis中的key都是存在hash表中的,所以keys命令需要把全部key拿出来一个一个对比。而redis执行命令的工作线程是单线程,所以其他命令就会因为keys命令而阻塞。 那我们怎么才能够在查找到目标键呢?在redis2.8.0的时候加入了scan命令,可以分批次扫描redis键。虽然在应用的时候会使得要查询到全部符合要求的key的时间变长, ...

redis中scan命令的实现

在一个天朗气清的日子,小灰登上了线上的redis打算查询数据。然而他只记得前缀而不知道整个键是多少,于是在命令行敲入了“keys xxx*”命令。 瞬间服务卡死,报警邮件堆满了邮箱,而小灰,只能目瞪狗呆的等待着即将降临的case study。 基本上,keys *命令都是在线上是被运维禁止的。 redis的键在键值对大小大于hash-max-ziplist-value且个数小于hash-max-ziplist-entries的时候,是存放在散列表数据结构中的,在运行keys命令的时候,需要遍历数据库键空间,把所有键都取出来后与keys后面的pattern匹配。 ...

redis缓存

缓存的三种问题 缓存穿透:大批量请求不存在的key,导致数据库压力增大。【解决方案】:布隆过滤器。 缓存击穿:同一时间大批量请求一个过期的key,导致这些请求在同一时间访问数据库。【解决方案】:获取数据库后回写这个过程申请分布式锁,只有一个请求能获取后回写,其他一直重试等待。 缓存雪崩:同一时间大批量key过期。【解决方案】:设置expire time的时候随机加1~5分钟的超时。 数据库和缓存一致性解决: ...

Redis分布式锁

todo: https://learnku.com/articles/4211/unlock-the-correct-position-of-the-redis-lock https://juejin.im/post/5cc165816fb9a03202221dd5 https://crossoverjie.top/2018/03/29/distributed-lock/distributed-lock-redis/ ...