typedef struct redisObject {
unsigned type:4;
unsigned encoding:4;
unsigned lru:LRU_BITS;
int refcount;
void *ptr;
} robj;

1.多线程引入的复杂性是极大的
- 首先,多线程引入之后,Redis原来的顺序执行特性就不复存在,为了支持事务的原子性、隔离性,Redis就不得不引入一些很复杂的实现;
- 其次,Redis的数据结构,可以说是极其高效,在单线程模式下做了很多特性的优化,如果引入多线程,那么所有底层数据结构都要改造为线程安全,这会是极其复杂的工作;
2.多线程带来额外的成本 除了引入复杂度,多线程还会带来额外的成本。包括:
- 上下文切换成本,多线程调度需要切换线程上下文,这个操作先存储当前线程的本地数据、程序指针等,然后载入另一个线程数据,这种内核操作的成本不可忽视。
- 同步机制的开销,一些公共资源,在单线程模式下直接访问就行了,多线程需要通过加锁等方式去进行同步,这也是不可忽视的CPU开销;
- 一个线程本身也占据内存大小,对Redis这种内存数据库而言,内存非常珍贵,多线程本身带来的内存使用的成本也需要谨慎决策。
性能 第一,Redis 的大部分操作在内存上完成,内存操作本身就特别快; 第二,Redis追求极致,选择了很多高效的数据结构,并做了非常多的优化,比如ziplist, hash,跳表,有时候一种对象底层有几种实现以应对不同场景。 第三,Redis 采用了多路复用机制,使其在网络 IO 操作中能并发处理大量的客户端请求,实现高吞吐量。
内存淘汰策略#

标准LRU需要维护双链表,内存成本巨大,所以Redis采用近似LRU采样来做淘汰,具体步骤是随机采样 n 个 key,这个采样个数默认为 5,然后根据时间戳淘汰掉最旧的那个 key,如果淘汰后内存还是不足,就继续随机采样来淘汰。
在3.0之后,Redis还针对近似LRU算法做了淘汰池优化,也就是维护一个候选池,池中的数据根据访问时间进行排序。第一次随机选取的key都会放入池中,然后淘汰掉最久未访问的,比如第一次选了5个,淘汰了1个,剩下4个继续留在池子里。
当池子装满了后,每次随机选取的key只有空闲时间大于 池子里当前空闲时间最小的key时,才会放入池中,并替换池子中空闲时间最小的 key , 然后将池中空闲时间最大的key“淘汰”掉;
LFU:使用带时间衰减的近似 LFU
