为什么Redis与其他的k-v存储相比不一样
有两个主要的原因
- redis在键-值数据库中是一个不同的发展方向,值可以包含更复杂的数据类型,同时许多原子操作定义在这些数据类型上。redis的数据类型和基本数据结构密切相关,没有额外的抽象层,同样对于程序员也是直接可见的。
- redis是一个在内存中但是可以持久化到磁盘上的数据库,所以它代表了一个不同的权衡,高速读写被实现,但是对数据集有限制,那就是不能大于内存的大小。在内存中的数据库还有另外的优点,内存中表示的复杂数据结构比一些在磁盘中的数据结构更容易操作,所以redis可以做很多操作而内部并不复杂。同时,两种磁盘存储格式(RDB和AOF)也不需要适合于随机存储。所以,数据是紧凑的,而且总是在末尾添加生成。
Redis的内存占用
下面给出一些例子:
- 一个空的实例~1MB
- 一百万个小的字符串key->value ~100MB
- 一百万个哈希key->value,表示一个有五个字段的对象 ~ 200MB
测试你的用例是很简单的。使用redis-benchmark工具生成随机数据,然后使用Info memory检查空间使用。
当存储一些相同的key的时候,64位系统将比32位系统使用更多的内存,除非key和value很小。这是因为在64位系统使用8个字节的指针。当然,64位系统的优点是你可以拥有更多的内存,所以为了运行大型的redis服务,一个64位系统或多或少是需要的。还有一种选择是分片。
我喜欢redis的高级操作和特性,但是我不喜欢它在内存中做了所有的事情,并且我不能拥有比内存更大的数据集。怎么计划改变这点?
在过去,redis开发者尝试用虚拟内存和别的系统,为了允许比内存更大的数据集的使用。但是最终我们很乐意只做好一件事:内存用来数据服务,磁盘用来数据存储。所以现在还没有计划来创建一个对于redis的磁盘上的后端。毕竟,redis是它当前设计的直接结果。
你真正的问题不是总共的内存需要,事实上你需要把你的数据切分到多个redis实例中。,请阅读Partitioning page获取更多信息。
Redis和一个磁盘上的数据库一起使用是个好主意吗?
是的,一个通常的设计模式是把写非常密集的小数据放在redis中,大的二进制数据块放在SQL数据库或在磁盘数据库中保持最终一致。
我是否可以做些事情来降低Redis的内存使用?
如果可以的话,使用32位的Redis 实例。同样,使用小的哈希、列表、有序集和整数集也是很好的,因为Redis能够在一些元素的特殊情况下表示那些数据类型,以一种更加紧凑的方式。更多的信息请参考Memory Optimization page。
如果Redis运行时内存不足会发生什么?
Redis要么被Linux kill,一个错误导致崩溃,要么就开始慢下来。现代操作系统的malloc()函数返回null是不常见的,通常服务开始调换,redis的性能开始降级,所以你可能会注意到有一些错误的事情。
INFO指令可以 报告redis正在使用的内存大小,所以你可以写个脚本通过检查一些临界条件来监视你的redis服务。
Redis有一个保护措施允许使用者设置一个内存使用的最大限度,在配置文件里使用 maxmemory选项来设置一个Redis可以使用的内存限制。如果限制达到,redis将回复写命令一个错误(但是仍然可以继续接受只读命令),或者当你使用redis作为缓存的情况下,当最大内存限制达到的时候,你可以配置redis来丢弃某些key值。
可以参考Redis as an LRU cache。
在Linux下后台存储失败且有一个fork()错误,虽然我有许多空闲内存
简短的回答:echo 1 > /proc/sys/vm/overcommit_memory
下面开始更长的答案:
Redis在后台的存储机制依赖于操作系统中fork的copy-on-write:也就是redis fork(创建一个子进程)是父进程的一个完整精确拷贝。子进程转储到磁盘上的数据库然后退出。理论上来说,子进程作为一个副本应该使用和父亲一样多的内存,但是实际上由于大部分现代操作系统的copy-on-write的实现,父进程和子进程将共享内存页。当他被父进程或者子进程改变的时候,一个内存页将被复制。因此,从理论上讲,当子进程存储的时候,所有内存页可能被改变,Linux不能提前告诉子进程多少内存被使用,所以如果overcommit_memory设置被设置为0,创建将会失败,除非有同样多的空闲内存。结果是,如果你有3GB的redis数据并且只有2GB的空闲内存,它将会失败。
把overcommit_memory设置为1来告诉Linux以更加乐观的方式来执行fork操作,并且这确实是你想要的。
Redis的磁盘快照是原子的吗?
是的,redis的后台存储进程总是被fork当服务没有执行执行的时候,所以内存中每个成为一个原子的指令从查看磁盘快照来说也是原子的。
Redis是单进程的,我怎么利用多CPU?
Redis中CPU成为你的瓶颈是非常不可能的,通常redis要么是内存要么就是网络绑定。例如,在一台普通的Linux系统上使用流水线redis每秒可以传输500k的请求,所以如果你的应用主要使用O(N) 或 O(log(N))的指令,很难使用太多的 CPU。
然而,为了CPU使用率最大化,你可以在同一个机器上启动多个redis实例,并把它们当作不同的服务对待。在有些时刻,单个机器可能还不够,所以如果你想使用多个CPU你可以开始思考一些方式去更早的碎片化。
使用多个redis实例请参考Partitioning page。
单个redis能持有的key的最大数量是多少?一个哈希表、列表、集合 、有序集合中元素的最大数量呢?
Redis可以处理2^32个key,在实际的测试中,单个实例至少处理2.5亿 个key。
每个哈希表、列表、集合、有序集合能持有 2^32个元素。
换句话说,你的限制可能就是你系统的可用内存。
我的从节点与主节点相比,有不同数量的key。为什么?
如果你使用有限制时间的key,这是正常的情况。下面是发生了什么:
- 在从节点第一次同步的时候,主节点生成一个RDB文件。
- 这个RDB文件不包括在主节点中已经过期的key。但是这些key仍然在内存中。
- 然而这些key仍然在主节点Redis的内存中,即使已经过期了。它们被考虑为不存在,但是内存不久之后将被回收。然而这些key不是数据集的一部分,在INFO中和使用
DBSIZE指令
被广告。 - 当从节点读取主节点生成的RDB文件,这些key将不会被load。
作为结果,使用者有许多设置了有效期的key在从节点中看着少很多是很常见的,但是在实例中并没有什么实际的影响。
Redis的真正意思?
它的意思是REmote DIctionary Server。
为什么要开始Redis项目?
最初,redis为了衡量LLOOGG。但是当我完成基本的服务工作,我有了一个把它分享给其他人的想法,然后redis就变成了一个开源的项目。