标签 redis 下的文章

我们在 Sky Betting&Gaming 中使用 Redis 作为共享内存缓存,用于那些需要跨 API 服务器或者 Web 服务器鉴别令牌之类的操作。在 Core Tribe 内,它用来帮助处理日益庞大的登录数量,特别是在繁忙的时候,我们在一分钟内登录数量会超过 20,000 人。这在很大程度上适用于数据存放在大量服务器的情况下(在 SSO 令牌用于 70 台 Apache HTTPD 服务器的情况下)。我们最近着手升级 Redis 服务器,此升级旨在使用 Redis 3.2 提供的原生集群功能。这篇博客希望解释为什么我们要使用集群、我们遇到的问题以及我们的解决方案。

在开始阶段(或至少在升级之前)

我们的传统缓存中每个缓存都包括一对 Redis 服务器,使用 keepalive 确保始终有一个主节点监听 浮动 IP floating IP 地址。当出现问题时,这些服务器对需要很大的精力来进行管理,而故障模式有时是非常各种各样的。有时,只允许读取它所持有的数据,而不允许写入的从属节点却会得到浮动 IP 地址,这种问题是相对容易诊断的,但会让无论哪个程序试图使用该缓存时都很麻烦。

新的应用程序

因此,这种情况下,我们需要构建一个新的应用程序,一个使用 共享内存缓存 shared in-memory cache 的应用程序,但是我们不希望对该缓存进行迂回的故障切换过程。因此,我们的要求是共享的内存缓存,没有单点故障,可以使用尽可能少的人为干预来应对多种不同的故障模式,并且在事件恢复之后也能够在很少的人为干预下恢复,一个额外的要求是提高缓存的安全性,以减少数据泄露的范围(稍后再说)。当时 Redis Sentinel 看起来很有希望,并且有许多程序支持代理 Redis 连接,比如 twemproxy。这会导致还要安装其它很多组件,它应该有效,并且人际交互最少,但它复杂而需要运行大量的服务器和服务,并且相互通信。

将会有大量的应用服务器与 twemproxy 进行通信,这会将它们的调用路由到合适的 Redis 主节点,twemproxy 将从 sentinal 集群获取主节点的信息,它将控制哪台 Redis 实例是主,哪台是从。这个设置是复杂的,而且仍有单点故障,它依赖于 twemproxy 来处理分片,来连接到正确的 Redis 实例。它具有对应用程序透明的优点,所以我们可以在理论上做到将现有的应用程序转移到这个 Redis 配置,而不用改变应用程序。但是我们要从头开始构建一个应用程序,所以迁移应用程序不是一个必需条件。

幸运的是,这个时候,Redis 3.2 出来了,而且内置了原生集群,消除了对单一 sentinel 集群需要。

它有一个更简单的设置,但 twemproxy 不支持 Redis 集群分片,它能为你分片数据,但是如果尝试在与分片不一致的集群中这样做会导致问题。有参考的指南可以使其匹配,但是集群可以自动改变形式,并改变分片的设置方式。它仍然有单点故障。正是在这一点上,我将永远感谢我的一位同事发现了一个 Node.js 的 Redis 的集群发现驱动程序,让我们完全放弃了 twemproxy。

因此,我们能够自动分片数据,故障转移和故障恢复基本上是自动的。应用程序知道哪些节点存在,并且在写入数据时,如果写入错误的节点,集群将自动重定向该写入。这是被选的配置,这让我们共享的内存缓存相当健壮,可以没有干预地应付基本的故障模式。在测试期间,我们的确发现了一些缺陷。复制是在一个接一个节点的基础上进行的,因此如果我们丢失了一个主节点,那么它的从节点会成为一个单点故障,直到死去的节点恢复服务,也只有主节点对集群健康投票,所以如果我们一下失去太多主节点,那么集群无法自我恢复。但这比我们过去的好。

向前进

随着使用集群 Redis 配置的新程序,我们对于老式 Redis 实例的状态变得越来越不适应,但是新程序与现有程序的规模并不相同(超过 30GB 的内存专用于我们最大的老式 Redis 实例数据库)。因此,随着 Redis 集群在底层得到了证实,我们决定迁移老式的 Redis 实例到新的 Redis 集群中。

由于我们有一个原生支持 Redis 集群的 Node.js Redis 驱动程序,因此我们开始将 Node.js 程序迁移到 Redis 集群。但是,如何将数十亿字节的数据从一个地方移动到另一个地方,而不会造成重大问题?特别是考虑到这些数据是认证令牌,所以如果它们错了,我们的终端用户将会被登出。一个选择是要求网站完全下线,将所有内容都指向新的 Redis 群集,并将数据迁移到其中,以希望获得最佳效果。另一个选择是切换到新集群,并强制所有用户再次登录。由于显而易见的原因,这些都不是非常合适的。我们决定采取的替代方法是将数据同时写入老式 Redis 实例和正在替换它的集群,同时随着时间的推移,我们将逐渐更多地向该集群读取。由于数据的有效期有限(令牌在几个小时后到期),这种方法可以导致零停机,并且不会有数据丢失的风险。所以我们这么做了。迁移是成功的。

剩下的就是服务于我们的 PHP 代码(其中还有一个项目是有用的,其它的最终是没必要的)的 Redis 的实例了,我们在这过程中遇到了一个困难,实际上是两个。首先,也是最紧迫的是找到在 PHP 中使用的 Redis 集群发现驱动程序,还要是我们正在使用的 PHP 版本。这被证明是可行的,因为我们升级到了最新版本的 PHP。我们选择的驱动程序不喜欢使用 Redis 的授权方式,因此我们决定使用 Redis 集群作为一个额外的安全步骤 (我告诉你,这将有更多的安全性)。当我们用 Redis 集群替换每个老式 Redis 实例时,修复似乎很直接,将 Redis 授权关闭,这样它将会响应所有的请求。然而,这并不是真的,由于某些原因,Redis 集群不会接受来自 Web 服务器的连接。 Redis 在版本 3 中引入的称为“保护模式”的新安全功能将在 Redis 绑定到任何接口时将停止监听来自外部 IP 地址的连接,并无需配置 Redis 授权密码。这被证明相当容易修复,但让我们保持警惕。

现在?

这就是我们现在的情况。我们已经迁移了我们的一些老式 Redis 实例,并且正在迁移其余的。我们通过这样做解决了我们的一些技术债务,并提高了我们的平台的稳定性。使用 Redis 集群,我们还可以扩展内存数据库并扩展它们。 Redis 是单线程的,所以只要在单个实例中留出更多的内存就会可以得到这么多的增长,而且我们已经紧跟在这个限制后面。我们期待着从新的集群中获得改进的性能,同时也为我们提供了扩展和负载均衡的更多选择。

未来怎么样?

我们解决了一些技术性债务,这使我们的服务更容易支持,更加稳定。但这并不意味着这项工作完成了,Redis 4 似乎有一些我们可能想要研究的功能。而且 Redis 并不是我们使用的唯一软件。我们将继续努力改进平台,缩短处理技术债务的时间,但随着客户群体的扩大,我们力求提供更丰富的服务,我们总是会遇到需要改进的事情。下一个挑战可能与每分钟超过 20,000次 登录到超过 40,000 次甚至更高的扩展有关。


via: http://engineering.skybettingandgaming.com/2017/09/25/redis-2-to-redis-3/

作者:Craig Stewart 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

完全无视安全功能的 Redis 服务器自创建以来饱受各种安全风险的困扰,Risk Based Security (RBS) 最近发现了 6338 台受到侵入的 Redis 服务器。

Redis 是一个在内存中以键值对方式存储数据的 NOSQL 数据库。据 DB-Engines 的统计数据,它在 2015 年度的数据库流行度位列第十,而在键值对数据库中排名第一

由于 Redis 以性能为第一考量,所以默认配置下该数据库没有任何的认证或其它的安全控制功能。

Redis 服务器存在 SSH 密钥创建漏洞

任何人只要知道你的 IP 地址和 Redis 的端口,就可以访问其中的任意内容。更糟糕的是,在 2015 年末,发现了一种攻击方式可以让任何人在你的 Redis 服务器上的 authorized\_keys 文件中存储 SSH 密钥——这意味着,攻击者将不需要任何密码即可取得 Redis 服务器上的 SSH 访问权限。

而现在,至少有三万台没有任何验证措施的 Redis 服务器暴露在互联网上,据 RBS 研究人员的称,已经有 6338 台 Redis 被窃取了 SSH 权限。

该公司在通过 Shodan 进行了非侵入式扫描之后得出了如上结论。RBS 的研究人员在分析了被入侵的服务器之后发现,它们上面存在着一个名为“crackit” 的 SSH 密钥,其关联的邮件地址 [email protected] 曾在之前的其它入侵事件中出现过。除了 [email protected] 这个地址出现过 5892 次之外,[email protected][email protected] 也分别出现了 385 次和 211 次。除了“crackit” 之外,还有一些名为“crackit\_key”, “qwe” ,“ck” 和 “crack” 之类的密钥名。据 RBS 分析,这表明它们来自多个组织或个人。

攻击者并不针对特定的 Redis 版本,任何版本都可能被黑

这些被攻击的 Redis 服务器的版本多达 106 个,从早期的 1.2.0. 到最新的 3.2.1 都有。

“从对这些数据的分析中得不到更进一步的结果,只能确认两件事,第一件事是这并非新出现的漏洞,第二是,有些服务器只是被侵入了,但是并没有被利用。”RBS 研究人员解释说

该公司建议系统管理员们升级其 Redis 服务器到最新的版本,并启用 3.2 版本新引入的“保护模式”。另外,不要将 Redis 服务器或者其它的数据库暴露在互联网上是最起码的安全准则。

今日关注

默认情况下, Redis 不进行任何验证即可访问,所以一般来说,Redis 服务器都会放置在内网或使用防火墙禁止外部访问。但现在至少有 30000 台 Redis 服务器暴露在公网上。可能有人觉得 Redis 上并无重要数据,暴露也不要紧。但是去年年底出现的一个安全攻击可以通过 Redis 创建 SSH 登录密钥,这就是说,存在安全缺陷的 Redis 服务器会导致主机上的 SSH 访问开放。目前据 RBS 的报告,有超过 6000 台的 Redis 服务器已经被攻击感染。

请系统管理员们尽快升级到最新版本,并启用相应的保护措施。

图文摘要

Canonical 和 Pivotal 公司达成合作,将成为 Pivotal Cloud Foundry 云平台上的首选操作系统。

Ubuntu 15.10 作为非 LTS 版本,只有九个月的支持期,它将在7月28日结束支持。

如果你在 Ubuntu 或其它支持 Snap 软件包的系统上运行过 GUI 程序,你可能注意到一些应用的样式不能跟随系统主题。现在,Canonical 宣布即将推出新的 Snap 桌面启动器,可以使 GUI 应用的主题样式和桌面主题保持一致。

大家好,本文的主题是 Redis,我们将要在 CentOS 7 上安装它。编译源代码,安装二进制文件,创建、安装文件。在安装了它的组件之后,我们还会配置 redis ,就像配置操作系统参数一样,目标就是让 redis 运行的更加可靠和快速。

Runnins Redis

Redis 服务器

Redis 是一个开源的多平台数据存储软件,使用 ANSI C 编写,直接在内存使用数据集,这使得它得以实现非常高的效率。Redis 支持多种编程语言,包括 Lua, C, Java, Python, Perl, PHP 和其他很多语言。redis 的代码量很小,只有约3万行,它只做“很少”的事,但是做的很好。尽管是在内存里工作,但是数据持久化的保存还是有的,而redis 的可靠性就很高,同时也支持集群,这些可以很好的保证你的数据安全。

构建 Redis

redis 目前没有官方 RPM 安装包,我们需要从源代码编译,而为了要编译就需要安装 Make 和 GCC。

如果没有安装过 GCC 和 Make,那么就使用 yum 安装。

yum install gcc make

官网下载 tar 压缩包。

curl http://download.redis.io/releases/redis-3.0.4.tar.gz -o redis-3.0.4.tar.gz

解压缩。

tar zxvf redis-3.0.4.tar.gz

进入解压后的目录。

cd redis-3.0.4

使用Make 编译源文件。

make

安装

进入源文件的目录。

cd src

复制 Redis 的服务器和客户端到 /usr/local/bin。

cp redis-server redis-cli /usr/local/bin

最好也把 sentinel,benchmark 和 check 复制过去。

cp redis-sentinel redis-benchmark redis-check-aof redis-check-dump /usr/local/bin

创建redis 配置文件夹。

mkdir /etc/redis

/var/lib/redis 下创建有效的保存数据的目录

mkdir -p /var/lib/redis/6379

系统参数

为了让 redis 正常工作需要配置一些内核参数。

配置 vm.overcommit_memory 为1,这可以避免数据被截断,详情见此

sysctl -w vm.overcommit_memory=1

修改 backlog 连接数的最大值超过 redis.conf 中的 tcp-backlog 值,即默认值511。你可以在kernel.org 找到更多有关基于 sysctl 的 ip 网络隧道的信息。

sysctl -w net.core.somaxconn=512

取消对透明巨页内存(transparent huge pages)的支持,因为这会造成 redis 使用过程产生延时和内存访问问题。

echo never > /sys/kernel/mm/transparent_hugepage/enabled

redis.conf

redis.conf 是 redis 的配置文件,然而你会看到这个文件的名字是 6379.conf ,而这个数字就是 redis 监听的网络端口。如果你想要运行超过一个的 redis 实例,推荐用这样的名字。

复制示例的 redis.conf 到 /etc/redis/6379.conf

cp redis.conf /etc/redis/6379.conf

现在编辑这个文件并且配置参数。

vi /etc/redis/6379.conf

daemonize

设置 daemonize 为 no,systemd 需要它运行在前台,否则 redis 会突然挂掉。

daemonize no

pidfile

设置 pidfile/var/run/redis_6379.pid

pidfile /var/run/redis_6379.pid

port

如果不准备用默认端口,可以修改。

port 6379

loglevel

设置日志级别。

loglevel notice

logfile

修改日志文件路径。

logfile /var/log/redis_6379.log

dir

设置目录为 /var/lib/redis/6379

dir /var/lib/redis/6379

安全

下面有几个可以提高安全性的操作。

Unix sockets

在很多情况下,客户端程序和服务器端程序运行在同一个机器上,所以不需要监听网络上的 socket。如果这和你的使用情况类似,你就可以使用 unix socket 替代网络 socket,为此你需要配置 port 为0,然后配置下面的选项来启用 unix socket。

设置 unix socket 的套接字文件。

 unixsocket /tmp/redis.sock

限制 socket 文件的权限。

unixsocketperm 700

现在为了让 redis-cli 可以访问,应该使用 -s 参数指向该 socket 文件。

redis-cli -s /tmp/redis.sock

requirepass

你可能需要远程访问,如果是,那么你应该设置密码,这样子每次操作之前要求输入密码。

requirepass "bTFBx1NYYWRMTUEyNHhsCg"

rename-command

想象一下如下指令的输出。是的,这会输出服务器的配置,所以你应该在任何可能的情况下拒绝这种访问。

CONFIG GET *

为了限制甚至禁止这条或者其他指令可以使用 rename-command 命令。你必须提供一个命令名和替代的名字。要禁止的话需要设置替代的名字为空字符串,这样禁止任何人猜测命令的名字会比较安全。

rename-command FLUSHDB "FLUSHDB_MY_SALT_G0ES_HERE09u09u"
rename-command FLUSHALL ""
rename-command CONFIG "CONFIG_MY_S4LT_GO3S_HERE09u09u"

Access Redis through unix with password and command changes

使用密码通过 unix socket 访问,和修改命令

快照

默认情况下,redis 会周期性的将数据集转储到我们设置的目录下的 dump.rdb 文件。你可以使用 save 命令配置转储的频率,它的第一个参数是以秒为单位的时间帧,第二个参数是在数据文件上进行修改的数量。

每隔15分钟并且最少修改过一次键。

save 900 1

每隔5分钟并且最少修改过10次键。

save 300 10

每隔1分钟并且最少修改过10000次键。

save 60 10000

文件 /var/lib/redis/6379/dump.rdb 包含了从上次保存以来内存里数据集的转储数据。因为它先创建临时文件然后替换之前的转储文件,这里不存在数据破坏的问题,你不用担心,可以直接复制这个文件。

开机时启动

你可以使用 systemd 将 redis 添加到系统开机启动列表。

复制示例的 init\_script 文件到 /etc/init.d,注意脚本名所代表的端口号。

cp utils/redis_init_script /etc/init.d/redis_6379

现在我们要使用 systemd,所以在 /etc/systems/system 下创建一个单位文件名字为 redis_6379.service

vi /etc/systemd/system/redis_6379.service

填写下面的内容,详情可见 systemd.service。

[Unit]
Description=Redis on port 6379

[Service]
Type=forking
ExecStart=/etc/init.d/redis_6379 start
ExecStop=/etc/init.d/redis_6379 stop

[Install]
WantedBy=multi-user.target

现在添加我之前在 /etc/sysctl.conf 里面修改过的内存过量使用和 backlog 最大值的选项。

vm.overcommit_memory = 1

net.core.somaxconn=512

对于透明巨页内存支持,并没有直接 sysctl 命令可以控制,所以需要将下面的命令放到 /etc/rc.local 的结尾。

echo never > /sys/kernel/mm/transparent_hugepage/enabled

总结

这样就可以启动了,通过设置这些选项你就可以部署 redis 服务到很多简单的场景,然而在 redis.conf 还有很多为复杂环境准备的 redis 选项。在一些情况下,你可以使用 replicationSentinel 来提高可用性,或者将数据分散在多个服务器上,创建服务器集群。

谢谢阅读。


via: http://linoxide.com/storage/install-redis-server-centos-7/

作者:Carlos Alberto 译者:ezio 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出