数据结构与内部编码
Redis对外主要提供了5种数据结构,分别是string、hash、list、set、sorted set
并且对于每一种数据结构redis都提供了至少2种相应的内部编码实现以应对不同的使用场景。
这么做的目的
- 对于用户的数据存储选择合适的处理策略以达到内存最优使用的目的,即采用以空间换取时间还是以时间换取空间策略
- 采用面向接口编程思想以达到很好的扩展性,比如对于list类型又完成了一种针对特定场景使用的内部编码实现,那么只需要将内部编码集成到list类型之中,而用户无需关心实际内部编码的使用情况,仍然使用list类型即可
redisObject
在Redis源码内部有一个redisObject
这样的对象或者说结构体,redis使用redisObject
表示所有的key-value。
它里面有很多属性,比较重要的就是数据类型type和编码方式encoding,如图所示。
单线程
redis在一个瞬间只会执行一条命令,所有命令以串行方式进行排列,等待顺序执行。如图所示当第一个get命令执行完成之后才会执行第二个get命令,其实这就是redis单线程最简单的一个表现。
理解redis单线程非常重要,同时这也是redis设计的精髓所在。
单线程为什么这么快?
1.纯内存
redis会将所有数据放在内存中,而内存的响应速度是非常快的。所以redis之所以能达到如此高性能是依赖于内存的。
其实无论你做了很多优化或者说代码的优化实际它的本质是数据放在内存当中。
2.非阻塞IO
redis使用了epoll模型作为IO多路复用的实现,redis自身也实现了事件处理,将epoll的连接、读写、关闭转换为自身的事件,不在网络IO上浪费过多的时间。
3.避免线程切换和竞态消耗
这其实也是单线程的特性,很多时候如果多线程没有达到一个合理的使用时,它甚至比单线程还要慢。
单线程注意事项
- 一次只运行一条命令
- 拒绝长(慢)命令(keys, flushall, flushdb, slow lua script, mutil/exec, operatebig value(collection))
- 其实不是真正的单线程,在执行
fysnc file descriptor
和close file descriptor
操作时也会单独开一个线程,了解即可