21 May 2014 |
简单的kv存储,除了set/get之外还支持append,setbit,inc等操作
kv的扩展,v是一个链表,链表的常见操作都可以使用
v使用ziplist
kv的扩展,v是一个字典,类似mongodb的文档
v使用dict
kv的扩展,v是一个类似C++中的set,唯一且可快速查找
v使用dict或者intset
kv的扩展,v是一个排序的set,排序的key是额外指定的一个score。 内部实现上,set还是使用的dict,并额外将数据插入一份到一个skiplist实现排序
v使用ziplist 或者 dict+zsklist
一种用于统计的数据结构 可以估计整个空间不重复数据的数目
pub/sub 跟zookeeper的功能非常相似, 在redis上可以建立一个或者多个channel, client可以往channel上发布message, 其他client可以监听这个channel, 监听者 能都能收到发布者发布的数据.
pub/sub在分布式系统中很常见, 常常用来做分布式系统的选举, 同步等.
redis最重要的数据结构,是一个可自动扩展的hash-table 每一个dict实际上最多持有2个hashtable,大部分情况下使用的是0 发生hash扩展时,会new一个1,然后逐步将0中的entry迁移到1中, 完成迁移后,释放掉旧的,把新的赋值给0
dict的每次expand都会将桶的数量double.
dict的迁移不是异步的,而是一旦需要迁移时,每次访问该dict, 就完成一个slot的迁移。
redis中,几乎所有支持快速查询的数据都是用dict来存储的。
ziplist是一个比较节省空间的双向“链表” 实际上名字虽然是链表, 但一个ziplist在内存中是连续的, 可以像双向链表一个使用, 但在ziplist中插入数据是需要做memmove的. 因为不保存指针, 然后一些表示长度的字段也用了5B表示法, 相对于一般双向链表, 它更省空间. 但是性能上的开销也要大得多.
zipmap在追求zip的道路上走得过头导致出现了明显的性能问题, 且修改会出现兼容性问题. 所以zipmap在目前的redis中已经被废弃.
intset在构造set时, 如果发现数据是int, short, 或者byte长度, 会根据实际长度优化使用空间. 但如果新insert的数据长度大于之前的预期, 就需要重新构造整个set.
redis中所有为了节省空间而设计的list, set, map都不适合大量item的存储.
跳跃表的一种实现,查询修改的效率接近红黑树。 redis中的实现有些特别,比如允许key重复。
zsklist在redis中用来给sorted set排序。
redis的协议有一个设计要点是可读,所以它可以说是一种文本协议。 不过可以传输二进制数据.
协议设计上有传递数据长度, 这样可以准备传输二进制数据.
redis支持Master-Slave模型
设计上这个没有上限,但slave越多master的同步压力越大。 redis还支持网状结构,slave可以再拥有自己的slave。
redis采取异步同步策略,slave与master始终会有同步延时。 redis会经可能快的同步数据。
redis采取了一个折中的策略: 1. master成功就算成功 2. 可以配置限制条件:如果slave的数量小于N, 或者slave与master的ping大于M, 则写操作失败.
redis内置2种数据持久化方案, RDB和AOF
RDB: redis会周期性的将整个db数据dump到本地的一个文件. RDB的完成过程是由redis fork出来的一个子进程来做, 并不会影响redis主进程本身.
RDB因为是fork子进程来处理所有数据, 所以它存在一个可能性, 就是在dump数据的过程中, 内存使用量可能会double.
AOF: redis将所有的写操作的请求协议append一个log文件中, redis重启时会replay该文件的数据.
RDB与AOF可以结合使用.
在单个实例无法保存所有数据,或者为了提高CPU利用率等情况下, 需要数据分割到多个实例.
分割的方案一般是range或者hash, hash又有简单的取模或者一致性hash等方案. 当redis仅仅作为cache使用时,一致性hash就已经足够,如果redis作为最终数据存储,那就需要完善的cluster方案. 主要是需要在多个node之间做数据的rebalance.
redis目前内置的partioning方案redis cluster还处于实验性质.
redis目前推荐的方案是使用外部组件Twemproxy.
redis的partitioning是基于key的, 如果某个key特别大, 大到一台机器无法存储, 这对于现有的redis partitiong方案来说都无法解决.
在cluster情况下,某些redis功能会失效, 主要是事务或者pipelining功能, 在处理多个key时, 如果这些key分布在不同机器上, 就会失败.
redis cluster跟Twemproxy不一样的是, 它没有引入一个proxy, 而是允许客户连接任意一个cluster中的redis实例, 如果某个client请求的数据不在当前实例, cluster会返回一个redirect, 告诉客户端正确的地址.
redis可以配置为一个lru cache服务, 当使用的内存数量超过指定的max值后, 会启用制定的lru策略