redis faq
23 March 2018
原文: Redis FAQ

Redis 与其他 key-value 存储有什么不同?

主要有以下两个原因。

  • Redis 有着更为复杂的数据结构并且提供对他们的原子性操作,这是一个不同于其他数据库的进化路径。Redis 的数据类型都是基于基本数据结构的同时对程序员透明,无需进行额外的抽象。
  • Redis 运行在内存中但是可以持久化到磁盘,所以在对不同数据集进行高速读写时需要权衡内存,应为数据量不能大于硬件内存。在内存数据库方面的另一个优点是, 相比在磁盘上相同的复杂的数据结构,在内存中操作起来非常简单,这样 Redis 可以做很多内部复杂性很强的事情。 同时,在磁盘格式方面他们是紧凑的以追加的方式产生的,因为他们并不需要进行随机访问。

Redis 的内存占用情况怎么样?

给你举个例子:100 万个键值对(键是 0 到 999999 值是字符串“hello world”)在我的 32 位的 Mac 笔记本上 用了 100MB。同样的数据放到一个 key 里只需要 16MB, 这是因为键值有一个很大的开销。 在 Memcached 上执行也是类似的结果,但是相对 Redis 的开销要小一点点,因为 Redis 会记录类型信息引用计数等等。

当然,大键值对时两者的比例要好很多。

64 位的系统比 32 位的需要更多的内存开销,尤其是键值对都较小时,这是因为 64 位的系统里指针占用了 8 个字节。 但是,当然,64 位系统支持更大的内存,所以为了运行大型的 Redis 服务器或多或少的需要使用 64 位的系统。

我喜欢 Reids 的高水平操作和功能,但我不喜欢所有数据都放在内存中,因为我没有一个大数据集的内存,有没有改变这方面的机会呢。

在过去,Redis 开发商尝试试用虚拟内存和其他系统为了让 RAM 数据集更大,但是毕竟我们非常高兴,如果我们能做好一件事:数据保存在内存,存储在磁盘。 但是现在没有计划创建一个基于磁盘的 Redis,毕竟目前的设计是直接的原因。

然而,许多大型系统的用户采用多个 Redis 节点通过客户端 Hash 的办法解决了大数据集分配的问题。Craigslist 和 Groupon 就是两个列子。

同时 Redis Cluster(一个 Redis 的子集自动分发和容错实现)正在开发中,这可能是很多使用案例的一个很好的解决方案

如果我的数据集需要使用非常大的内存,我不希望使用一致性哈希或其他方式将数据集分布在不同的节点,我还能采用 Redis 吗?

一个可行的方案是同时使用传统数据库(Mysql 或者其他的)和 Redis,Redis 里面存放状态信息(元数据,小但经常写的信息),和所有其他读写频繁的数据:用户身份验证 token, 使用 Redis List 存放与时间顺序有关的 id 列表、编码等等。然后使用 MySQL(或其他)作为存储引擎来存放更大的数据, 创建一个自增长 ID 作为主键和一个较大的 BLOB 字段作为数据字段,访问 MySQL 的数据只能通过主键(ID) 。执行查询操作时,通过 Redis 读取数据, 但是当有读取打数据时需要通过主键(ID)访问 MySQL 数据库。 ,

都有哪些办法可以降低 Redis 的内存使用情况呢?

如果你使用的是 32 位的 Redis 实例,可以好好利用 Hash,list,sorted set,set 等集合类型数据,因为通常情况下很多小的 Key-Value 可以用更紧凑的方式存放到一起。

Redis 的内存用完了会发生什么?

随着现代操作系统的 malloc(),返回 NULL 是不常见的,通常服务器会启动 swap 交换,这样 Redis 的性能会随之降低,您也可能会发现某些不妥。

INFO 命令可以查看 Redis 的使用量,因此您可以编写一个监视 Redis 服务器状态的临界监控脚本以检查服务器的状态。 或者可以在配置文件中使用 “maxmemory” 配置 Redis 可以使用的最大内存,如果达到设置的上限,Redis 的写命令会返回错误信息(但是读命令还可以正常返回。) 或者你可以将 Redis 当缓存来使用配置淘汰机制,当 Redis 达到内存上限时会冲刷掉旧的内容。

在 liunx 下即使有很多的 RAM 通过 fork()调用后台保存还是会失败!

简短的回答:
echo 1 > /proc/sys/vm/overcommit_memory :)

下面是长的回答:
Redis background saving schema relies on the copy-on-write semantic of fork in modern operating systems: Redis forks (creates a child process) that is an exact copy of the parent. The child process dumps the DB on disk and finally exits. In theory the child should use as much memory as the parent being a copy, but actually thanks to the copy-on-write semantic implemented by most modern operating systems the parent and child process will share the common memory pages. A page will be duplicated only when it changes in the child or in the parent. Since in theory all the pages may change while the child process is saving, Linux can’t tell in advance how much memory the child will take, so if the overcommit_memory setting is set to zero fork will fail unless there is as much free RAM as required to really duplicate all the parent memory pages, with the result that if you have a Redis dataset of 3 GB and just 2 GB of free memory it will fail. Setting overcommit_memory to 1 says Linux to relax and perform the fork in a more optimistic allocation fashion, and this is indeed what you want for Redis. A good source to understand how Linux Virtual Memory work and other alternatives for overcommit_memory and overcommit_ratio is this classic from Red Hat Magazine, “Understanding Virtual Memory”.

Redis 的 on-disk-snapshots 是原子的吗?

是的, 当 redis 前台在执行命令时后台保存进程是 fork(2)ed, 所以任何命令在 RAM 里是原子操作的,在磁盘快照里面也同样是原子的。

Redis 是单线程的,我怎么提高多核 CPU 的利用率?

CPU 不太可能是 Redis 的瓶颈,一般内存和网络才有可能是。 例如使用 Redis 的管道(pipelining)在 liunx 系统上运行可以达到 500K 的 RPS(requests per second) ,因此,如果您的应用程序主要使用 O(N) 或者 O(log(N)) 的 命令,他们几乎不需要使用什么 CPU。

然而,为了最大限度的使用 CPU,可以在同一个服务器部署多个 Redis 的实例,并把他们当作不同的服务器来使用,在某些时候,无论如何一个服务器是不够的,

所以,如果你想使用多个 CPU,你可以考虑一下分片(shard) 。。

在 Redis 的客户端类库里面,比如 RB(Ruby 的客户端)和 Predis(最常用的 PHP 客户端之一),能够使用一致性哈希(consistent hashing)来处理多个 Redis 实例。

一个 Redis 实例最多能存放多少的 keys,List、Set、Sorted Set 他们最多能存放多少元素?

理论上 Redis 可以处理多达 2^32 的 keys,并且在实际中进行了测试,每个实例至少存放了 2 亿 5 千万的 keys。我们正在测试一些较大的值。

任何 list、set、和 sorted set 都可以放 2^32 个元素。

换句话说,Redis 的存储极限是系统中的可用内存值。

Redis 是什么意思?

他的意思是 REmote DIctionary Server。

你为什么开始 Redis 项目?

本来,Redis 是为了 LLOOGG 开始的。 但之后,我得到了基本服务的工作,我喜欢将自己的想法分享给其他工作者,并把 Redis 转变成一个开源项目。