首页> 搜索结果页
"redis动态扩容" 检索
共 195 条结果
Redis开发运维实践高可用和集群简述
10.1 概念 在本文档中,高可用主要指的是解决尽可能在不丢失数据的前提下不间断服务问题,由于redis是异步复制,因此不保证数据完全不丢失,在这个场景下并不实现动态横向扩容,只能进行纵向扩容,你只要加内存,启动redis,设置maxmemory即可。而分片(Sharding)主要指的是解决在线动态横向扩容缩容问题,当然为了稳定也进行高可用部署配置,即包含成对的主从关系。 10.2 高可用主要场景和对应思路 适用于redis非重度用户,内存占用不大,总体内存大小的增长趋势可预估,有一定停机时间的系统——纵向扩容即可满足,可以对全库进行主从复制即满足需求而不需要做分片,一般针对单个小型项目的cache 等场景。一般采用一主多从的sentinel方案进行部署。 10.3 分片主要场景和对应思路 分片是为了应对业务增长带来的数据增长,需要对动态横向扩容有一定要求时采用。对于一般的分片采用一致性哈希,它极大的优化机器增删时带来的哈希目标漂移问题。同时对于Hash目标漂移时产生的严重的数据倾斜,可以利用虚拟节点来优化。基本上,物理节点有了一定规模后,只要不是同时挂多个节点,或者同时扩容多个节点,数据分片不会有太大的扰动。穿透过Cache的请求后端存储可以抗住即可。 稍微复杂的方案是可以使用“预分片(Pre-Sharding)”的方案,也称为按“桶”进行数据划分,即分配一个相当大的集合,对Key哈希的结果落在这个集合中,集合的每个元素又与具体的物理节点存在多对一的路由映射关系,这张路由表由一个配置中心进行维护。其实,一致性哈希中的虚拟节点,实际上也可以归类到Pre-Sharding方案中。换句话说,只要是key经过两次哈希,第一次Hash到虚拟节点,第二次Hash到物理节点,都可以算作Pre-Sharding。只不过区别在于,一致性哈希的第二次Hash其路由表是按照算法固定的,而分桶的第二次Hash其路由表是第三方可配的。 10.4 适用场景对比列表 --- 动态扩容能力 系统复杂度 开发复杂度 运维复杂度 主从复制+Sentinel No 简单 简单 简单 Twemproxy No 简单 简单 稍微复杂 3.0 Cluster Yes 简单 简单 复杂 Codis Yes 复杂 简单 复杂 应用层面presharding Yes 复杂 复杂 视开发的水平而定 本文为《Redis开发运维实践指南》内容,该书作者为黄鹏程,已授权云栖社区转载。
文章
运维 · NoSQL · Redis · Sentinel · 算法 · 存储
2017-05-08
性价比神器!99元一年的阿里云256MB高性能Redis性能测试及应用介绍
介绍 Redis是一个开源的key-value类型的数据库缓存和存储系统,同时Redis提供了丰富的数据结构用来支持多样的业务chan场景,比如hashes,lists,sets还有ordered sets及其他类型。云数据库Redis提供了兼容Redis协议的数据库服务,提供单机和集群两种模式,提供了全套的容灾切换、故障迁移、在线扩容、性能优化的数据库解决方案。本文我们将介绍如何使用阿里云Redis服务作为PHP服务的session存储。PHP的session存储作为php会话信息的存储单元,默认的PHP使用文件来存储session会话信息。同时PHP支持使用扩展的存储单元来作为会话信息的存储,通过扩展的session能够满足多台PHP服务器共享会话信息。 架构优势 Redis云服务主从版本默认双机热备 Redis云服务主从版本兼容性高,支持lua、事物,并且兼容Redis3.0的地理位置GEO计算 Redis云服务性能优越,最大性能可以达到10WQPS Redis云服务主从版本数据持久化,每秒AOF Fsync,并且支持备份恢复 Redis云服务主从版本256MB内存小性能高,性价比非常适合小内存的业务场景 Redis云服务主从版本支持动态扩容,用户在业务增长之后可以动态升级 购买Redis云服务 访问Redis控制台,点击创建实例 选择256MB按量付费,每个用户都能享受一次99元包年256MB的折扣 云Redis控制台使用介绍指南 测试Redis云服务 Redis云服务提供了文本协议进行访问,我们可以通过telnet进行服务的简单测试,实例的域名可以在控制台点击实例详情页面查看到,测试方法如下: [root@ECS~]# telnet HOST 6379 Trying IP... Connected to HOST. Escape character is '^]'. auth PASSWORD #回车 +OK #回复 ping #回车 +PONG #回复 quit #回车 +OK #回复 Connection closed by foreign host. 如果购买的实例能够按上面正常回复说明购买的实例能够正常使用。 性能测试 测试工具:https://github.com/RedisLabs/memtier_benchmark 测试客户端:华东1阿里云ECS 四核8GB内存 测试Redis:华东1阿里云256MBRedis实例 测试命令: ./memtier_benchmark --server HOST -p 6379 -P redis --threads=16 --clients=4 -a PASSWORD --data-size=128 --test-time=600 --ratio=1:10 --key-pattern=S:S 测试结果: 安装PHP扩展 代码下载 git clone https://github.com/phpredis/phpredis 初始化配置,切换到代码目录输入phpize然后输入./configure进行配置 编译安装,在执行完成./configure之后检查有没有异常,如果没有则执行make; make install即可 配置PHP扩展 PHP的会话存储定义在php.ini文件中,用户可以通过执行以下PHP代码找到PHP配置文件的路径。 <?php phpinfo() ?> 通常如果使用apache对应的配置文件在/etc/php5/apache2/php.ini,如果是nginx则在/usr/local/php/etc/php.ini,通过sudo vim 文件路径来修改对应的PHP配置如下,其中HOST还有PASSWORD需要换成对应实例域名和密码。 session.save_handler = redis session.save_path = "tcp://HOST:6379?auth=PASSWORD" 重启PHP服务则后续PHP的session信息将存储在阿里云Redis上,用户可以随着业务量的增长来随时对云Redis扩容。 结论 云数据库Redis提供了方便的Redis云服务,通过主备来保证实例的高可用,并提供了弹性的扩展能力,用户可以按需购买使用,同时阿里云Redis可以作为PHP的session信息存储管理单元,解决用户分布式session存储的困扰
文章
存储 · 测试技术 · PHP · Apache · 数据库
2017-04-18
Codis--分布式redis架构设计
Codis是一个分布式Redis解决方案,与官方的纯P2P的模式不同,Codis采用的是Proxy-based的方案。今天我们介绍一下Codis及下一个大版本RebornDB的设计,同时会介绍一些Codis在实际应用场景中的tips。最后抛砖引玉,会介绍一下我对分布式存储的一些观点和看法,望各位首席们雅正(黄旭东)。 一、 Redis,RedisCluster和Codis Redis:想必大家的架构中,Redis已经是一个必不可少的部件,丰富的数据结构和超高的性能以及简单的协议,让Redis能够很好的作为数据库的上游缓存层。但是我们会比较担心Redis的单点问题,单点Redis容量大小总受限于内存,在业务对性能要求比较高的情况下,理想情况下我们希望所有的数据都能在内存里面,不要打到数据库上,所以很自然的就会寻求其他方案。 比如,SSD将内存换成了磁盘,以换取更大的容量。更自然的想法是将Redis变成一个可以水平扩展的分布式缓存服务,在Codis之前,业界只有Twemproxy,但是Twemproxy本身是一个静态的分布式Redis方案,进行扩容/缩容时候对运维要求非常高,而且很难做到平滑的扩缩容。Codis的目标其实就是尽量兼容Twemproxy的基础上,加上数据迁移的功能以实现扩容和缩容,最终替换Twemproxy。从豌豆荚最后上线的结果来看,最后完全替换了Twem,大概2T左右的内存集群。 Redis Cluster :与Codis同期发布正式版的官方cluster,我认为有优点也有缺点,作为架构师,我并不会在生产环境中使用,原因有两个: cluster的数据存储模块和分布式的逻辑模块是耦合在一起的,这个带来的好处是部署异常简单,all-in-the-box,没有像Codis那么多概念,组件和依赖。但是带来的缺点是,你很难对业务进行无痛的升级。比如哪天Redis cluster的分布式逻辑出现了比较严重的bug,你该如何升级?除了滚动重启整个集群,没什么好办法。这个比较伤运维。 对协议进行了较大的修改,对客户端不太友好,目前很多客户端已经成为事实标准,而且很多程序已经写好了,让业务方去更换Redisclient,是不太现实的,而且目前很难说有哪个Rediscluster客户端经过了大规模生产环境的验证,从HunanTV开源的Rediscluster proxy上可以看得出这个影响还是蛮大的,否则就会支持使用cluster的client了。 Codis:和Redis cluster不同的是,Codis采用一层无状态的proxy层,将分布式逻辑写在proxy上,底层的存储引擎还是Redis本身(尽管基于Redis2.8.13上做了一些小patch),数据的分布状态存储于zookeeper(etcd)中,底层的数据存储变成了可插拔的部件。这个事情的好处其实不用多说,就是各个部件是可以动态水平扩展的,尤其无状态的proxy对于动态的负载均衡,还是意义很大的,而且还可以做一些有意思的事情,比如发现一些slot的数据比较冷,可以专门用一个支持持久化存储的server group来负责这部分slot,以节省内存,当这部分数据变热起来时,可以再动态的迁移到内存的server group上,一切对业务透明。比较有意思的是,在Twitter内部弃用Twmeproxy后,t家自己开发了一个新的分布式Redis解决方案,仍然走的是proxy-based路线。不过没有开源出来。可插拔存储引擎这个事情也是Codis的下一代产品RebornDB在做的一件事情。btw,RebornDB和它的持久化引擎都是完全开源的,见https://github.com/reborndb/reborn和https://github.com/reborndb/qdb。当然这样的设计的坏处是,经过了proxy,多了一次网络交互,看上去性能下降了一些,但是记住,我们的proxy是可以动态扩展的,整个服务的QPS并不由单个proxy的性能决定(所以生产环境中我建议使用LVS/HA Proxy或者Jodis),每个proxy其实都是一样的。 本文转自 抚琴煮酒 51CTO博客,原文链接:http://blog.51cto.com/yuhongchun/1901146,如需转载请自行联系原作者
文章
存储 · NoSQL · Redis · 运维 · 缓存 · 数据库 · 负载均衡 · 固态存储 · 架构师
2017-11-23
Codis--分布式redis架构设计
Codis是一个分布式Redis解决方案,与官方的纯P2P的模式不同,Codis采用的是Proxy-based的方案。今天我们介绍一下Codis及下一个大版本RebornDB的设计,同时会介绍一些Codis在实际应用场景中的tips。最后抛砖引玉,会介绍一下我对分布式存储的一些观点和看法,望各位首席们雅正(黄旭东)。 一、 Redis,RedisCluster和Codis Redis:想必大家的架构中,Redis已经是一个必不可少的部件,丰富的数据结构和超高的性能以及简单的协议,让Redis能够很好的作为数据库的上游缓存层。但是我们会比较担心Redis的单点问题,单点Redis容量大小总受限于内存,在业务对性能要求比较高的情况下,理想情况下我们希望所有的数据都能在内存里面,不要打到数据库上,所以很自然的就会寻求其他方案。 比如,SSD将内存换成了磁盘,以换取更大的容量。更自然的想法是将Redis变成一个可以水平扩展的分布式缓存服务,在Codis之前,业界只有Twemproxy,但是Twemproxy本身是一个静态的分布式Redis方案,进行扩容/缩容时候对运维要求非常高,而且很难做到平滑的扩缩容。Codis的目标其实就是尽量兼容Twemproxy的基础上,加上数据迁移的功能以实现扩容和缩容,最终替换Twemproxy。从豌豆荚最后上线的结果来看,最后完全替换了Twem,大概2T左右的内存集群。 Redis Cluster :与Codis同期发布正式版的官方cluster,我认为有优点也有缺点,作为架构师,我并不会在生产环境中使用,原因有两个: cluster的数据存储模块和分布式的逻辑模块是耦合在一起的,这个带来的好处是部署异常简单,all-in-the-box,没有像Codis那么多概念,组件和依赖。但是带来的缺点是,你很难对业务进行无痛的升级。比如哪天Redis cluster的分布式逻辑出现了比较严重的bug,你该如何升级?除了滚动重启整个集群,没什么好办法。这个比较伤运维。 对协议进行了较大的修改,对客户端不太友好,目前很多客户端已经成为事实标准,而且很多程序已经写好了,让业务方去更换Redisclient,是不太现实的,而且目前很难说有哪个Rediscluster客户端经过了大规模生产环境的验证,从HunanTV开源的Rediscluster proxy上可以看得出这个影响还是蛮大的,否则就会支持使用cluster的client了。 Codis:和Redis cluster不同的是,Codis采用一层无状态的proxy层,将分布式逻辑写在proxy上,底层的存储引擎还是Redis本身(尽管基于Redis2.8.13上做了一些小patch),数据的分布状态存储于zookeeper(etcd)中,底层的数据存储变成了可插拔的部件。这个事情的好处其实不用多说,就是各个部件是可以动态水平扩展的,尤其无状态的proxy对于动态的负载均衡,还是意义很大的,而且还可以做一些有意思的事情,比如发现一些slot的数据比较冷,可以专门用一个支持持久化存储的server group来负责这部分slot,以节省内存,当这部分数据变热起来时,可以再动态的迁移到内存的server group上,一切对业务透明。比较有意思的是,在Twitter内部弃用Twmeproxy后,t家自己开发了一个新的分布式Redis解决方案,仍然走的是proxy-based路线。不过没有开源出来。可插拔存储引擎这个事情也是Codis的下一代产品RebornDB在做的一件事情。btw,RebornDB和它的持久化引擎都是完全开源的,见https://github.com/reborndb/reborn和https://github.com/reborndb/qdb。当然这样的设计的坏处是,经过了proxy,多了一次网络交互,看上去性能下降了一些,但是记住,我们的proxy是可以动态扩展的,整个服务的QPS并不由单个proxy的性能决定(所以生产环境中我建议使用LVS/HA Proxy或者Jodis),每个proxy其实都是一样的。 本文转自 抚琴煮酒 51CTO博客,原文链接:http://blog.51cto.com/yuhongchun/1901146,如需转载请自行联系原作者
文章
存储 · NoSQL · Redis · 运维 · 缓存 · 数据库 · 负载均衡 · 固态存储 · 架构师
2017-11-22
redis的主从配置 扩容
由于redis的集群功能没有完全编写好,见:http://redis.io/topics/cluster-spec 集群只有测试版的第8个版本redis3.0.0 见 http://redis.io/download 但是redis可以做主从设置   Redis的主从复制策略是通过其持久化的rdb文件来实现的,其过程是先dump出rdb文件,将rdb文件全量传输给slave,然后再将dump后的操作实时同步到slave中。下面是一篇介绍Redis复制原理的文章,文章作者为新浪微博的田琪同学(@摇摆巴赫)。 本文会讨论一下Redis的复制功能以及Redis复制机制本身的优缺点以及集群搭建问题。 Redis复制流程概述 Redis的复制功能是完全建立在之前我们讨论过的基于内存快照的持久化策略基础上的,也就是说无论你的持久化策略选择的是什么,只要用到了 Redis的复制功能,就一定会有内存快照发生,那么首先要注意你的系统内存容量规划,原因可以参考我上一篇文章中提到的Redis磁盘IO问题。 Redis复制流程在Slave和Master端各自是一套状态机流转,涉及的状态信息是: Slave 端: REDIS_REPL_NONE REDIS_REPL_CONNECT REDIS_REPL_CONNECTED Master端: REDIS_REPL_WAIT_BGSAVE_START REDIS_REPL_WAIT_BGSAVE_END REDIS_REPL_SEND_BULK REDIS_REPL_ONLINE 整个状态机流程过程如下: 1.Slave端在配置文件中添加了slave of指令,于是Slave启动时读取配置文件,初始状态为REDIS_REPL_CONNECT。 2.Slave端在定时任务serverCron(Redis内部的定时器触发事件)中连接Master,发送sync命令,然后阻塞等待master发送回其内存快照文件(最新版的Redis已经不需要让Slave阻塞)。 3.Master端收到sync命令简单判断是否有正在进行的内存快照子进程,没有则立即开始内存快照,有则等待其结束,当快照完成后会将该文件发送给Slave端。 4.Slave端接收Master发来的内存快照文件,保存到本地,待接收完成后,清空内存表,重新读取Master发来的内存快照文件,重建整个内存表数据结构,并最终状态置位为 REDIS_REPL_CONNECTED状态,Slave状态机流转完成。 5.Master端在发送快照文件过程中,接收的任何会改变数据集的命令都会暂时先保存在Slave网络连接的发送缓存队列里(list数据结构),待快照完成后,依次发给Slave,之后收到的命令相同处理,并将状态置位为 REDIS_REPL_ONLINE。 整个复制过程完成,流程如下图所示: Redis复制机制的缺陷 从上面的流程可以看出,Slave从库在连接Master主库时,Master会进行内存快照,然后把整个快照文件发给Slave,也就是没有象MySQL那样有复制位置的概念,即无增量复制,这会给整个集群搭建带来非常多的问题。 比如一台线上正在运行的Master主库配置了一台从库进行简单读写分离,这时Slave由于网络或者其它原因与Master断开了连接,那么当 Slave进行重新连接时,需要重新获取整个Master的内存快照,Slave所有数据跟着全部清除,然后重新建立整个内存表,一方面Slave恢复的 时间会非常慢,另一方面也会给主库带来压力。 所以基于上述原因,如果你的Redis集群需要主从复制,那么最好事先配置好所有的从库,避免中途再去增加从库。 Cache还是Storage 在我们分析过了Redis的复制与持久化功能后,我们不难得出一个结论,实际上Redis目前发布的版本还都是一个单机版的思路,主要的问题集中在,持久化方式不够成熟,复制机制存在比较大的缺陷,这时我们又开始重新思考Redis的定位:Cache还是Storage? 如果作为Cache的话,似乎除了有些非常特殊的业务场景,必须要使用Redis的某种数据结构之外,我们使用Memcached可能更合适,毕竟Memcached无论客户端包和服务器本身更久经考验。 如果是作为存储Storage的话,我们面临的最大的问题是无论是持久化还是复制都没有办法解决Redis单点问题,即一台Redis挂掉了,没有太好的办法能够快速的恢复,通常几十G的持久化数据,Redis重启加载需要几个小时的时间,而复制又有缺陷,如何解决呢? Redis可扩展集群搭建 1. 主动复制避开Redis复制缺陷。 既然Redis的复制功能有缺陷,那么我们不妨放弃Redis本身提供的复制功能,我们可以采用主动复制的方式来搭建我们的集群环境。 所谓主动复制是指由业务端或者通过代理中间件对Redis存储的数据进行双写或多写,通过数据的多份存储来达到与复制相同的目的,主动复制不仅限于 用在Redis集群上,目前很多公司采用主动复制的技术来解决MySQL主从之间复制的延迟问题,比如Twitter还专门开发了用于复制和分区的中间件 gizzard(https://github.com/twitter/gizzard) 。 主动复制虽然解决了被动复制的延迟问题,但也带来了新的问题,就是数据的一致性问题,数据写2次或多次,如何保证多份数据的一致性呢?如果你的应用 对数据一致性要求不高,允许最终一致性的话,那么通常简单的解决方案是可以通过时间戳或者vector clock等方式,让客户端同时取到多份数据并进行校验,如果你的应用对数据一致性要求非常高,那么就需要引入一些复杂的一致性算法比如Paxos来保证 数据的一致性,但是写入性能也会相应下降很多。 通过主动复制,数据多份存储我们也就不再担心Redis单点故障的问题了,如果一组Redis集群挂掉,我们可以让业务快速切换到另一组Redis上,降低业务风险。 2. 通过presharding进行Redis在线扩容。 通过主动复制我们解决了Redis单点故障问题,那么还有一个重要的问题需要解决:容量规划与在线扩容问题。 我们前面分析过Redis的适用场景是全部数据存储在内存中,而内存容量有限,那么首先需要根据业务数据量进行初步的容量规划,比如你的业务数据需 要100G存储空间,假设服务器内存是48G,那么根据上一篇我们讨论的Redis磁盘IO的问题,我们大约需要3~4台服务器来存储。这个实际是对现有 业务情况所做的一个容量规划,假如业务增长很快,很快就会发现当前的容量已经不够了,Redis里面存储的数据很快就会超过物理内存大小,那么如何进行 Redis的在线扩容呢? Redis的作者提出了一种叫做presharding的方案来解决动态扩容和数据分区的问题,实际就是在同一台机器上部署多个Redis实例的方式,当容量不够时将多个实例拆分到不同的机器上,这样实际就达到了扩容的效果。 拆分过程如下: 1.在新机器上启动好对应端口的Redis实例。 2.配置新端口为待迁移端口的从库。 3.待复制完成,与主库完成同步后,切换所有客户端配置到新的从库的端口。 4.配置从库为新的主库。 5.移除老的端口实例。 6.重复上述过程迁移好所有的端口到指定服务器上。 以上拆分流程是Redis作者提出的一个平滑迁移的过程,不过该拆分方法还是很依赖Redis本身的复制功能的,如果主库快照数据文件过大,这个复制的过程也会很久,同时会给主库带来压力。所以做这个拆分的过程最好选择为业务访问低峰时段进行。 Redis复制的改进思路 我们线上的系统使用了我们自己改进版的Redis,主要解决了Redis没有增量复制的缺陷,能够完成类似Mysql Binlog那样可以通过从库请求日志位置进行增量复制。 我们的持久化方案是首先写Redis的AOF文件,并对这个AOF文件按文件大小进行自动分割滚动,同时关闭Redis的Rewrite命令,然后 会在业务低峰时间进行内存快照存储,并把当前的AOF文件位置一起写入到快照文件中,这样我们可以使快照文件与AOF文件的位置保持一致性,这样我们得到 了系统某一时刻的内存快照,并且同时也能知道这一时刻对应的AOF文件的位置,那么当从库发送同步命令时,我们首先会把快照文件发送给从库,然后从库会取 出该快照文件中存储的AOF文件位置,并将该位置发给主库,主库会随后发送该位置之后的所有命令,以后的复制就都是这个位置之后的增量信息了。 Redis与MySQL的结合 目前大部分互联网公司使用MySQL作为数据的主要持久化存储,那么如何让Redis与MySQL很好的结合在一起呢?我们主要使用了一种基于MySQL作为主库,Redis作为高速数据查询从库的异构读写分离的方案。 为此我们专门开发了自己的MySQL复制工具,可以方便的实时同步MySQL中的数据到Redis上。 (MySQL-Redis 异构读写分离) 总结: 1.Redis的复制功能没有增量复制,每次重连都会把主库整个内存快照发给从库,所以需要避免向在线服务的压力较大的主库上增加从库。 2.Redis的复制由于会使用快照持久化方式,所以如果你的Redis持久化方式选择的是日志追加方式(aof),那么系统有可能在同一时刻既 做aof日志文件的同步刷写磁盘,又做快照写磁盘操作,这个时候Redis的响应能力会受到影响。所以如果选用aof持久化,则加从库需要更加谨慎。 3.可以使用主动复制和presharding方法进行Redis集群搭建与在线扩容。 本文加上之前的2篇文章基本将Redis的最常用功能和使用场景与优化进行了分析和讨论,实际Redis还有很多其它辅助的一些功能,Redis的作者也在不断尝试新的思路,这里就不一一列举了,有兴趣的朋友可以研究下,也很欢迎一起讨论,我的微博(http://weibo.com/bachmozart ) @摇摆巴赫。   来源:http://blog.nosqlfan.com/html/3153.html   分类: 分布式消息框架 本文转自快乐就好博客园博客,原文链接:http://www.cnblogs.com/happyday56/p/3955534.html,如需转载请自行联系原作者
文章
存储 · NoSQL · 关系型数据库 · MySQL · Redis · 中间件 · 算法 · 缓存
2017-06-25
Redis的复制流程
归纳几点 redis复制缺陷 主动复制 通过presharding进行Redis在线扩容 内存规划,避免向在线服务的压力较大的主库上增加从库 新的持久化方案 redis的数据类型 Redis与MySQL的结合,开发了自己的MySQL复制工具,可以方便的实时同步MySQL中的数据到Redis上 redis的读写性能是否在一定的框架下会变化   background AOF rewrite terminated with success 以下是作者的博文 http://www.xuchanggang.cn/archives/980.html Redis的复制功能是基于内存快照的持久化策略基础上的,也就是说无论你的持久化策略选择的是什么,只要用到了Redis的复制功能,就一定会有内存快照发生,那么首先要注意你的系统内存容量规划 Redis复制流程在Slave和Master端各自是一套状态机流转,涉及的状态信息如下: Slave 端: REDIS_REPL_NONE REDIS_REPL_CONNECT REDIS_REPL_CONNECTED Master端:           REDIS_REPL_WAIT_BGSAVE_START REDIS_REPL_WAIT_BGSAVE_END REDIS_REPL_SEND_BULK REDIS_REPL_ONLINE 整个状态机流程过程如下: (1).Slave端在配置文件中添加了slave of指令,于是Slave启动时读取配置文件,初始状态为REDIS_REPL_CONNECT。 (2).Slave端在定时任务serverCron(Redis内部的定时器触发事件)中连接Master,发送sync命令,然后阻塞等待master发送回其内存快照文件(最新版的Redis已经不需要让Slave阻塞)。      (3).Master端收到sync命令简单判断是否有正在进行的内存快照子进程,没有则立即开始内存快照,有则等待其结束,当快照完成后会将该文件发送给Slave端。      (4).Slave端接收Master发来的内存快照文件,保存到本地,待接收完成后,清空内存表,重新读取Master发来的内存快照文件,重建整个内存表数据结构,并最终状态置位为 REDIS_REPL_CONNECTED状态,Slave状态机流转完成。      (5).Master端在发送快照文件过程中,接收的任何会改变数据集的命令都会暂时先保存在Slave网络连接的发送缓存队列里(list数据结构),待快照完成后,依次发给Slave,之后收到的命令相同处理,并将状态置位为 REDIS_REPL_ONLINE。 整个复制过程完成,流程如下图所示:   Redis复制机制的缺陷       从上面的流程可以看出,Slave从库在连接Master主库时,Master会进行内存快照,然后把整个快照文件发给Slave,      也就是没有象MySQL那样有复制位置的概念,即无增量复制,这会给整个集群搭建带来非常多的问题。 比如一台线上正在运行的Master主库配置了一台从库进行简单读写分离,这时Slave由于网络或者其它原因与Master断开了连接,      那么当Slave进行重新连接时,需要重新获取整个Master的内存快照,Slave所有数据跟着全部清除,      然后重新建立整个内存表,一方面Slave恢复的时间会非常慢,另一方面也会给主库带来压力。 所以基于上述原因,如果你的Redis集群需要主从复制,那么最好事先配置好所有的从库,避免中途再去增加从库。 Cache还是Storage 在我们分析过了Redis的复制与持久化功能后,我们不难得出一个结论,实际上Redis目前发布的版本还都是一个单机版的思路,主要的问题集中在,持久化方式不够成熟,复制机制存在比较大的缺陷,这时我们又开始重新思考Redis的定位:Cache还是Storage? 如果作为Cache的话,似乎除了有些非常特殊的业务场景,必须要使用Redis的某种数据结构之外,我们使用Memcached可能更合适,毕竟Memcached无论客户端包和服务器本身更久经考验。 如果是作为存储Storage的话,我们面临的最大的问题是无论是持久化还是复制都没有办法解决Redis单点问题,即一台Redis挂掉了,没有太好的办法能够快速的恢复,通常几十G的持久化数据,Redis重启加载需要几个小时的时间,而复制又有缺陷,如何解决呢? Redis可扩展集群搭建 1. 主动复制避开Redis复制缺陷。 既然Redis的复制功能有缺陷,那么我们不妨放弃Redis本身提供的复制功能,我们可以采用主动复制的方式来搭建我们的集群环境。 所谓主动复制是指由业务端或者通过代理中间件对Redis存储的数据进行双写或多写,通过数据的多份存储来达到与复制相同的目的,                主动复制不仅限于用在Redis集群上,目前很多公司采用主动复制的技术来解决MySQL主从之间复制的延迟问题,                比如Twitter还专门开发了用于复制和分区的中间件gizzard(https://github.com/twitter/gizzard) 。 主动复制虽然解决了被动复制的延迟问题,但也带来了新的问题,就是数据的一致性问题,数据写2次或多次,如何保证多份数据的一致性呢?                如果你的应用对数据一致性要求不高,允许最终一致性的话,那么通常简单的解决方案是可以通过时间戳或者vector clock等方式,                让客户端同时取到多份数据并进行校验,如果你的应用对数据一致性要求非常高,那么就需要引入一些复杂的一致性算法比如Paxos来保证数据的一致性,                但是写入性能也会相应下降很多。 通过主动复制,数据多份存储我们也就不再担心Redis单点故障的问题了,如果一组Redis集群挂掉,我们可以让业务快速切换到另一组Redis上,降低业务风险。 2. 通过presharding进行Redis在线扩容。 通过主动复制我们解决了Redis单点故障问题,那么还有一个重要的问题需要解决:容量规划与在线扩容问题。 我们前面分析过Redis的适用场景是全部数据存储在内存中,而内存容量有限,那么首先需要根据业务数据量进行初步的容量规划,                 比如你的业务数据需要100G存储空间,假设服务器内存是48G,我们大约需要3~4台服务器来存储。                 这个实际是对现有业务情况所做的一个容量规划,假如业务增长很快,很快就会发现当前的容量已经不够了,Redis里面存储的数据很快就会超过物理内存大小,                 那么如何进行Redis的在线扩容呢? Redis的作者提出了一种叫做presharding的方案来解决动态扩容和数据分区的问题,      实际就是在同一台机器上部署多个Redis实例的方式,当容量不够时将多个实例拆分到不同的机器上,这样实际就达到了扩容的效果。 拆分过程如下: 在新机器上启动好对应端口的Redis实例。 配置新端口为待迁移端口的从库。 待复制完成,与主库完成同步后,切换所有客户端配置到新的从库的端口。 配置从库为新的主库。 移除老的端口实例。 重复上述过程迁移好所有的端口到指定服务器上。      以上拆分流程是Redis作者提出的一个平滑迁移的过程,不过该拆分方法还是很依赖Redis本身的复制功能的,      如果主库快照数据文件过大,这个复制的过程也会很久,同时会给主库带来压力。所以做这个拆分的过程最好选择为业务访问低峰时段进行。 Redis复制的改进思路 我们线上的系统使用了我们自己改进版的Redis,主要解决了Redis没有增量复制的缺陷,能够完成类似Mysql Binlog那样可以通过从库请求日志位置进行增量复制。 我们的持久化方案是首先写Redis的AOF文件,并对这个AOF文件按文件大小进行自动分割滚动,同时关闭Redis的Rewrite命令,      然后会在业务低峰时间进行内存快照存储,并把当前的AOF文件位置一起写入到快照文件中,这样我们可以使快照文件与AOF文件的位置保持一致性,      这样我们得到了系统某一时刻的内存快照,并且同时也能知道这一时刻对应的AOF文件的位置,那么当从库发送同步命令时,      我们首先会把快照文件发送给从库,然后从库会取出该快照文件中存储的AOF文件位置,并将该位置发给主库,主库会随后发送该位置之后的所有命令,      以后的复制就都是这个位置之后的增量信息了。   Redis与MySQL的结合 目前大部分互联网公司使用MySQL作为数据的主要持久化存储,那么如何让Redis与MySQL很好的结合在一起呢?      我们主要使用了一种基于MySQL作为主库,Redis作为高速数据查询从库的异构读写分离的方案。 为此我们专门开发了自己的MySQL复制工具,可以方便的实时同步MySQL中的数据到Redis上。   (MySQL-Redis 异构读写分离) 总结: Redis的复制功能没有增量复制,每次重连都会把主库整个内存快照发给从库,所以需要避免向在线服务的压力较大的主库上增加从库。 Redis的复制由于会使用快照持久化方式,所以如果你的Redis持久化方式选择的是日志追加方式(aof),      那么系统有可能在同一时刻既做aof日志文件的同步刷写磁盘,又做快照写磁盘操作,这个时候Redis的响应能力会受到影响。      所以如果选用aof持久化,则加从库需要更加谨慎。 可以使用主动复制和presharding方法进行Redis集群搭建与在线扩容。 本文转自 liqius 51CTO博客,原文链接:http://blog.51cto.com/szgb17/1705129,如需转载请自行联系原作者
文章
存储 · NoSQL · 关系型数据库 · MySQL · Redis · 中间件 · 算法 · 缓存
2017-11-27
分区:怎样将数据分布到多个redis实例
分区是将你的数据分发到不同redis实例上的一个过程,每个redis实例只是你所有key的一个子集。文档第一部分将介绍分区概念,第二部分介绍分区的另外一种可选方案。 为什么分区非常有用 Redis分区主要有两个目的: 分区可以让Redis管理更大的内存,Redis将可以使用所有机器的内存。如果没有分区,你最多只能使用一台机器的内存。 分区使Redis的计算能力通过简单地增加计算机得到成倍提升,Redis的网络带宽也会随着计算机和网卡的增加而成倍增长。 分区基本概念 有许多分区标准。假如我们有4个Redis实例R0, R1, R2, R3,有一批用户数据user:1, user:2, … ,那么有很多存储方案可以选择。从另一方面说,有很多different systems to map方案可以决定用户映射到哪个Redis实例。 一种最简单的方法就是范围分区,就是将不同范围的对象映射到不同Redis实例。比如说,用户ID从0到10000的都被存储到R0,用户ID从10001到20000被存储到R1,依此类推。 这是一种可行方案并且很多人已经在使用。但是这种方案也有缺点,你需要建一张表存储数据到redis实例的映射关系。这张表需要非常谨慎地维护并且需要为每一类对象建立映射关系,所以redis范围分区通常并不像你想象的那样运行,比另外一种分区方案效率要低很多。 另一种可选的范围分区方案是散列分区,这种方案要求更低,不需要key必须是object_name:<id>的形式,如此简单: 使用散列函数 (如 crc32 )将键名称转换为一个数字。例:键foobar, 使用crc32(foobar)函数将产生散列值93024922。 对转换后的散列值进行取模,以产生一个0到3的数字,以便可以使这个key映射到4个Redis实例当中的一个。93024922 % 4 等于 2, 所以 foobar 会被存储到第2个Redis实例。 R2 注意: 对一个数字进行取模,在大多数编程语言中是使用运算符% 还有很多分区方法,上面只是给出了两个简单示例。有一种比较高级的散列分区方法叫一致性哈希,并且有一些客户端和代理(proxies)已经实现。 不同的分区实现方案 分区可以在程序的不同层次实现。 客户端分区就是在客户端就已经决定数据会被存储到哪个redis节点或者从哪个redis节点读取。大多数客户端已经实现了客户端分区。 代理分区 意味着客户端将请求发送给代理,然后代理决定去哪个节点写数据或者读数据。代理根据分区规则决定请求哪些Redis实例,然后根据Redis的响应结果返回给客户端。redis和memcached的一种代理实现就是Twemproxy 查询路由(Query routing) 的意思是客户端随机地请求任意一个redis实例,然后由Redis将请求转发给正确的Redis节点。Redis Cluster实现了一种混合形式的查询路由,但并不是直接将请求从一个redis节点转发到另一个redis节点,而是在客户端的帮助下直接redirected到正确的redis节点。 分区的缺点 有些特性在分区的情况下将受到限制: 涉及多个key的操作通常不会被支持。例如你不能对两个集合求交集,因为他们可能被存储到不同的Redis实例(实际上这种情况也有办法,但是不能直接使用交集指令)。 同时操作多个key,则不能使用Redis事务. 分区使用的粒度是key,不能使用一个非常长的排序key存储一个数据集(The partitioning granularity is the key, so it is not possible to shard a dataset with a single huge key like a very big sorted set). 当使用分区的时候,数据处理会非常复杂,例如为了备份你必须从不同的Redis实例和主机同时收集RDB / AOF文件。 分区时动态扩容或缩容可能非常复杂。Redis集群在运行时增加或者删除Redis节点,能做到最大程度对用户透明地数据再平衡,但其他一些客户端分区或者代理分区方法则不支持这种特性。然而,有一种预分片的技术也可以较好的解决这个问题。 持久化数据还是缓存? 无论是把Redis当做持久化的数据存储还是当作一个缓存,从分区的角度来看是没有区别的。当把Redis当做一个持久化的存储(服务)时,一个key必须严格地每次被映射到同一个Redis实例。当把Redis当做一个缓存(服务)时,即使Redis的其中一个节点不可用而把请求转给另外一个Redis实例,也不对我们的系统产生什么影响,我们可用任意的规则更改映射,进而提高系统的高可用(即系统的响应能力)。 一致性哈希能够实现当一个key的首选的节点不可用时切换至其他节点。同样地,如果你增加了一个新节点,立刻就会有新的key被分配至这个新节点。 重要结论如下: 如果Redis被当做缓存使用,使用一致性哈希实现动态扩容缩容。 如果Redis被当做一个持久化存储使用,必须使用固定的keys-to-nodes映射关系,节点的数量一旦确定不能变化。否则的话(即Redis节点需要动态变化的情况),必须使用可以在运行时进行数据再平衡的一套系统,而当前只有Redis集群可以做到这样 - Redis 集群已经可用 2015.4.1. 预分片 从上面获知,除非我们把Redis当做缓存使用,否则(在生产环境动态)增加和删除节点将非常麻烦,但是使用固定的keys-instances则比较简单。 一般情况下随着时间的推移,数据存储需求总会发生变化。今天可能10个Redis节点就够了,但是明天可能就需要增加到50个节点。 既然Redis是如此的轻量(单实例只使用1M内存),为防止以后的扩容,最好的办法就是一开始就启动较多实例。即便你只有一台服务器,你也可以一开始就让Redis以分布式的方式运行,使用分区,在同一台服务器上启动多个实例。 一开始就多设置几个Redis实例,例如32或者64个实例,对大多数用户来说这操作起来可能比较麻烦,但是从长久来看做这点牺牲是值得的。 这样的话,当你的数据不断增长,需要更多的Redis服务器时,你需要做的就是仅仅将Redis实例从一台服务迁移到另外一台服务器而已(而不用考虑重新分区的问题)。一旦你添加了另一台服务器,你需要将你一半的Redis实例从第一台机器迁移到第二台机器。 使用Redis复制技术,你可以做到极短或者不停机地对用户提供服务: 在你新服务器启动一个空Redis实例。 把新Redis实例配置为原实例的slave节点 停止你的客户端 更新你客户端配置,以便启用新的redis实例(更新IP)。 在新Redis实例中执行SLAVEOF NO ONE命令 (更新配置后)重启你的客户端 停止你原服务器的Redis实例 Redis分区实现 截止到目前,我们从理论上讨论了Redis分区,但是实际上是怎样的呢?你应该采用哪种实现方案呢? Redis 集群 Redis集群是自动分片和高可用的首选方案。新的集群方案2015年4月1日就已经可用。2015.4.1 Google论文. 你可以从这里Cluster tutorial了解更多。 当Redis集群可用,并且有兼容Redis 集群客户端可用于你的编程语言,Redis 集群将成为Redis分区的实际标准. Redis集群是 query routing 和 client side partitioning的一种混合实现。 Twemproxy Twemproxy是Twitter维护的(缓存)代理系统,代理Memcached的ASCII协议和Redis协议。它是单线程程序,使用c语言编写,运行起来非常快。它是采用Apache 2.0 license的开源软件。 Twemproxy支持自动分区,如果其代理的其中一个Redis节点不可用时,会自动将该节点排除(这将改变原来的keys-instances的映射关系,所以你应该仅在把Redis当缓存时使用Twemproxy)。 Twemproxy本身不存在单点问题,因为你可以启动多个Twemproxy实例,然后让你的客户端去连接任意一个Twemproxy实例。 Twemproxy是Redis客户端和服务器端的一个中间层,由它来处理分区功能应该不算复杂,并且应该算比较可靠的。 更多关于Twemproxy in this antirez blog post. 支持一致性哈希的客户端 相对于Twemproxy,另一种可选的分区方案是在客户端实现一致性哈希或者其他类似算法。有很多客户端已经支持一致性哈希,如 Redis-rb 和 Predis. 请检查 Redis客户端完整列表 以确认在你想要使用的编程语言,有成熟的一致性哈希客户端实现。 本文作者:陈群 本文来自云栖社区合作伙伴rediscn,了解相关信息可以关注redis.cn网站。
文章
存储 · 缓存 · NoSQL · Redis · 算法 · Apache · C语言 · 数据处理
2018-02-27
Redis复制与可扩展集群搭建
Redis复制流程概述 Redis的复制功能是完全建立在之前我们讨论过的基于内存快照的持久化策略基础上的,也就是说无论你的持久化策略选择的是什么,只要用到了Redis的复制功能,就一定会有内存快照发生,那么首先要注意你的系统内存容量规划,原因可以参考我上一篇文章中提到的Redis磁盘IO问题。 Redis复制流程在Slave和Master端各自是一套状态机流转,涉及的状态信息是: Slave 端: REDIS_REPL_NONE REDIS_REPL_CONNECT REDIS_REPL_CONNECTED Master端: REDIS_REPL_WAIT_BGSAVE_START REDIS_REPL_WAIT_BGSAVE_END REDIS_REPL_SEND_BULK REDIS_REPL_ONLINE 整个状态机流程过程如下: Slave端在配置文件中添加了slave of指令,于是Slave启动时读取配置文件,初始状态为REDIS_REPL_CONNECT。 Slave端在定时任务serverCron(Redis内部的定时器触发事件)中连接Master,发送sync命令,然后阻塞等待master发送回其内存快照文件(最新版的Redis已经不需要让Slave阻塞)。 Master端收到sync命令简单判断是否有正在进行的内存快照子进程,没有则立即开始内存快照,有则等待其结束,当快照完成后会将该文件发送给Slave端。 Slave端接收Master发来的内存快照文件,保存到本地,待接收完成后,清空内存表,重新读取Master发来的内存快照文件,重建整个内存表数据结构,并最终状态置位为 REDIS_REPL_CONNECTED状态,Slave状态机流转完成。 Master端在发送快照文件过程中,接收的任何会改变数据集的命令都会暂时先保存在Slave网络连接的发送缓存队列里(list数据结构),待快照完成后,依次发给Slave,之后收到的命令相同处理,并将状态置位为 REDIS_REPL_ONLINE。 整个复制过程完成,流程如下图所示: Redis复制机制的缺陷 从上面的流程可以看出,Slave从库在连接Master主库时,Master会进行内存快照,然后把整个快照文件发给Slave,也就是没有象MySQL那样有复制位置的概念,即无增量复制,这会给整个集群搭建带来非常多的问题。 比如一台线上正在运行的Master主库配置了一台从库进行简单读写分离,这时Slave由于网络或者其它原因与Master断开了连接,那么当Slave进行重新连接时,需要重新获取整个Master的内存快照,Slave所有数据跟着全部清除,然后重新建立整个内存表,一方面Slave恢复的时间会非常慢,另一方面也会给主库带来压力。 所以基于上述原因,如果你的Redis集群需要主从复制,那么最好事先配置好所有的从库,避免中途再去增加从库。 Cache还是Storage 在我们分析过了Redis的复制与持久化功能后,我们不难得出一个结论,实际上Redis目前发布的版本还都是一个单机版的思路,主要的问题集中在,持久化方式不够成熟,复制机制存在比较大的缺陷,这时我们又开始重新思考Redis的定位:Cache还是Storage? 如果作为Cache的话,似乎除了有些非常特殊的业务场景,必须要使用Redis的某种数据结构之外,我们使用Memcached可能更合适,毕竟Memcached无论客户端包和服务器本身更久经考验。 如果是作为存储Storage的话,我们面临的最大的问题是无论是持久化还是复制都没有办法解决Redis单点问题,即一台Redis挂掉了,没有太好的办法能够快速的恢复,通常几十G的持久化数据,Redis重启加载需要几个小时的时间,而复制又有缺陷,如何解决呢? Redis可扩展集群搭建 1. 主动复制避开Redis复制缺陷。 既然Redis的复制功能有缺陷,那么我们不妨放弃Redis本身提供的复制功能,我们可以采用主动复制的方式来搭建我们的集群环境。 所谓主动复制是指由业务端或者通过代理中间件对Redis存储的数据进行双写或多写,通过数据的多份存储来达到与复制相同的目的,主动复制不仅限于用在Redis集群上,目前很多公司采用主动复制的技术来解决MySQL主从之间复制的延迟问题,比如Twitter还专门开发了用于复制和分区的中间件gizzard(https://github.com/twitter/gizzard) 。 主动复制虽然解决了被动复制的延迟问题,但也带来了新的问题,就是数据的一致性问题,数据写2次或多次,如何保证多份数据的一致性呢?如果你的应用对数据一致性要求不高,允许最终一致性的话,那么通常简单的解决方案是可以通过时间戳或者vector clock等方式,让客户端同时取到多份数据并进行校验,如果你的应用对数据一致性要求非常高,那么就需要引入一些复杂的一致性算法比如Paxos来保证数据的一致性,但是写入性能也会相应下降很多。 通过主动复制,数据多份存储我们也就不再担心Redis单点故障的问题了,如果一组Redis集群挂掉,我们可以让业务快速切换到另一组Redis上,降低业务风险。 2. 通过presharding进行Redis在线扩容。 通过主动复制我们解决了Redis单点故障问题,那么还有一个重要的问题需要解决:容量规划与在线扩容问题。 我们前面分析过Redis的适用场景是全部数据存储在内存中,而内存容量有限,那么首先需要根据业务数据量进行初步的容量规划,比如你的业务数据需要100G存储空间,假设服务器内存是48G,那么根据上一篇我们讨论的Redis磁盘IO的问题,我们大约需要3~4台服务器来存储。这个实际是对现有业务情况所做的一个容量规划,假如业务增长很快,很快就会发现当前的容量已经不够了,Redis里面存储的数据很快就会超过物理内存大小,那么如何进行Redis的在线扩容呢? Redis的作者提出了一种叫做presharding的方案来解决动态扩容和数据分区的问题,实际就是在同一台机器上部署多个Redis实例的方式,当容量不够时将多个实例拆分到不同的机器上,这样实际就达到了扩容的效果。 拆分过程如下: 在新机器上启动好对应端口的Redis实例。 配置新端口为待迁移端口的从库。 待复制完成,与主库完成同步后,切换所有客户端配置到新的从库的端口。 配置从库为新的主库。 移除老的端口实例。 重复上述过程迁移好所有的端口到指定服务器上。 以上拆分流程是Redis作者提出的一个平滑迁移的过程,不过该拆分方法还是很依赖Redis本身的复制功能的,如果主库快照数据文件过大,这个复制的过程也会很久,同时会给主库带来压力。所以做这个拆分的过程最好选择为业务访问低峰时段进行。 Redis复制的改进思路 我们线上的系统使用了我们自己改进版的Redis,主要解决了Redis没有增量复制的缺陷,能够完成类似Mysql Binlog那样可以通过从库请求日志位置进行增量复制。 我们的持久化方案是首先写Redis的AOF文件,并对这个AOF文件按文件大小进行自动分割滚动,同时关闭Redis的Rewrite命令,然后会在业务低峰时间进行内存快照存储,并把当前的AOF文件位置一起写入到快照文件中,这样我们可以使快照文件与AOF文件的位置保持一致性,这样我们得到了系统某一时刻的内存快照,并且同时也能知道这一时刻对应的AOF文件的位置,那么当从库发送同步命令时,我们首先会把快照文件发送给从库,然后从库会取出该快照文件中存储的AOF文件位置,并将该位置发给主库,主库会随后发送该位置之后的所有命令,以后的复制就都是这个位置之后的增量信息了。 Redis与MySQL的结合 目前大部分互联网公司使用MySQL作为数据的主要持久化存储,那么如何让Redis与MySQL很好的结合在一起呢?我们主要使用了一种基于MySQL作为主库,Redis作为高速数据查询从库的异构读写分离的方案。 为此我们专门开发了自己的MySQL复制工具,可以方便的实时同步MySQL中的数据到Redis上。 (MySQL-Redis 异构读写分离) 总结: Redis的复制功能没有增量复制,每次重连都会把主库整个内存快照发给从库,所以需要避免向在线服务的压力较大的主库上增加从库。 Redis的复制由于会使用快照持久化方式,所以如果你的Redis持久化方式选择的是日志追加方式(aof),那么系统有可能在同一时刻既做aof日志文件的同步刷写磁盘,又做快照写磁盘操作,这个时候Redis的响应能力会受到影响。所以如果选用aof持久化,则加从库需要更加谨慎。 可以使用主动复制和presharding方法进行Redis集群搭建与在线扩容。 本文加上之前的2篇文章基本将Redis的最常用功能和使用场景与优化进行了分析和讨论,实际Redis还有很多其它辅助的一些功能,Redis的作者也在不断尝试新的思路,这里就不一一列举了,有兴趣的朋友可以研究下,也很欢迎一起讨论,我的微博(http://weibo.com/bachmozart ) @摇摆巴赫。
文章
存储 · NoSQL · 关系型数据库 · MySQL · Redis · 中间件 · 算法 · 缓存
2013-03-13
web前端求职必会之Redis常见面试题答疑
  web前端求职必会之Redis常见面试题答疑,Redis(全称:Remote Dictionary Server 远程字典服务)是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。很多web前端求职时都会被问到Redis相关问题,尤其是在BRT类名企,接下来就给大家分享web前端求职必会的Redis常见面试题及答案。  1、Redis相比memcached有哪些优势?  1) memcached所有的值均是简单的字符串,redis作为其替代者, 支持更为丰富的数据类型;  2) redis的速度比memcached快很多;  3) redis可以持久化其数据。  2、Redis有哪几种数据淘汰策略?  noeviction:返回错误当内存限制达到并且客户端尝试执行会让更多内存被使用的命令(大部分的写入指令,但DEL和几个例外)。  allkeys-lru: 尝试回收最少使用的键(LRU),使得新添加的数据有空间存放。  volatile-lru: 尝试回收最少使用的键(LRU),但仅限于在过期集合的键,使得新添加的数据有空间存放。  allkeys-random: 回收随机的键使得新添加的数据有空间存放。  volatile-random: 回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键。volatile-ttl: 回收在过期集合的键,并且优先回收存活时间(TTL)较短的键,使得新添加的数据有空间存放。  3、Redis是单线程还是多线程?有何优势?  Redis是单线程,但是Redis 6发布后,它其实是支持多线程的。Redis是多线程的优势有两点:  1)单线程Redis的性能瓶颈主要在于网络的IO消耗,所以我们在优化的方向就是要提高网络IO性能。  2)Redis 6 引入的多线程IO特性对性能提升至少是一倍以上。Redis的多线程部分只是用来处理网络数据的读写和协议解析,执行命令仍然是单线程。  4、Redis主从复制会出现哪些问题?  1)一旦主节点宕机,从节点晋升为主节点,同时需要修改应用方的主节点地址,还需要命令所有从节点去复制新的主节点,整个过程需要人工干预。  2)主节点的写能力受到单机的限制。  3)主节点的存储能力受到单机的限制。  4)原生复制的弊端在早期的版本中也会比较突出,比如:redis复制中断后,从节点会发起psync。此时如果同步不成功,则会进行全量同步,主库执行全量备份的同时,可能会造成毫秒或秒级的卡顿。  5、为什么Redis需要把所有数据放到内存中?  Redis为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘。所以Redis具有快速和数据持久化的特征。如果不将数据放在内存中,磁盘I/O速度为严重影响Redis的性能。在内存越来越便宜的今天,Redis将会越来越受欢迎。  如果设置了最大使用的内存,则数据已有记录数达到内存限值后不能继续插入新值。  6、有哪些Redis分区实现方案?  客户端分区就是在客户端就已经决定数据会被存储到哪个Redis节点或者从哪个Redis节点读取。大多数客户端已经实现了客户端分区。代理分区 意味着客户端将请求发送给代理,然后代理决定去哪个节点写数据或者读数据。  代理根据分区规则决定请求哪些Redis实例,然后根据Redis的响应结果返回给客户端。Redis和memcached的一种代理实现就是Twemproxy查询路由(Query routing) 的意思是客户端随机地请求任意一个Redis实例,然后由Redis将请求转发给正确的Redis节点。  Redis Cluster实现了一种混合形式的查询路由,但并不是直接将请求从一个Redis节点转发到另一个Redis节点,而是在客户端的帮助下直接redirected到正确的Redis节点。  7、Redis持久化数据和缓存怎么做扩容?  如果Redis被当做缓存使用,使用一致性哈希实现动态扩容缩容。如果Redis被当做一个持久化存储使用,必须使用固定的keys-to-nodes映射关系,节点的数量一旦确定不能变化。否则的话(即Redis节点需要动态变化的情况),必须使用可以在运行时进行数据再平衡的一套系统,而当前只有Redis集群可以做到这样。  8、Redis与其他key-value存储有什么不同?  Redis有着更为复杂的数据结构并且提供对他们的原子性操作,这是一个不同于其他数据库的进化路径。Redis的数据类型都是基于基本数据结构的同时对程序员透明,无需进行额外的抽象。Redis运行在内存中但是可以持久化到磁盘,所以在对不同数据集进行高速读写时需要权衡内存,应为数据量不能大于硬件内存。在内存数据库方面的另一个优点是, 相比在磁盘上相同的复杂的数据结构,在内存中操作起来非常简单,这样Redis可以做很多内部复杂性很强的事情。 同时,在磁盘格式方面他们是紧凑的以追加的方式产生的,因为他们并不需要进行随机访问。
文章
存储 · 缓存 · NoSQL · 前端开发 · 程序员 · API · Redis · 数据库 · C语言
2020-03-07
你知道吗?我喜欢你六年了——微博Redis定制化之路
在2016杭州云栖大会的“开源数据库之Redis专场”上,微博研发中心数据库技术负责人肖鹏带来了《微博的Redis定制之路》的精彩分享。分享中,他重点介绍了微博六年来使用Redis遇到的问题和积累的实践经验。  以下内容根据演讲PPT及现场分享整理。 微博属于国内较早一批Redis用户,微博目前由近千台Redis物理机,近万个Redis实例,日访问量达到万亿以上,从微博开始使用Redis到现在可以分为三个阶段:探索期、发育期、稳定期。最初上线试水Redis,是因为使用MySQL遇到问题,无法解决业务瓶颈。六年的时间内,微博在使用Redis过程中积累了大量的经验和技巧。 探索期:野蛮生长 微博最初使用Redis时,是采用Reids替换掉架构中的MC,形成Web+Redis+MySQL的架构。经过一段时间的使用,发现Redis的数据结构十分丰富,并且自带持久化功能。因此微博采取了一步大胆的尝试,将三层架构中的MySQL剥出,将Redis最为落地存储的数据库,将三层结构变为两层结构。 在初期使用Redis时遇到很多问题:首先性能上由于Redis原生是单线程的,在进行重操作,尤其是bgsave时会出现明显的卡顿,业务波动;其次故障恢复问题,宕机后恢复主从速度慢,经常出现带宽洪峰问题;此外,运维上也存在复杂度问题,版本升级频繁,主库切换常态化。 为了解决Bgsave带来的问题:一是可以从主线程中独立出来Bio thread,专门执行Bgsave等操作,避免干扰;二是在Redis中内置Cronsave功能,控制备份时间;三是放弃Bgaofrewrite。 在Redis替代MySQL存储落地的过程中,微博对Redis也进行很多定制化改造:  修改了AOF机制,增加原本不存在的POS位;  修改了Replication机制,实现基于AOF+POS位置的数据同步  修改落地机制,改为RDB+AOF滚动机制,保障数据持久化存储。 在使用Redis过程,同样可以对其热升级,简化运维复杂度:主程序中为全局的数据结构,其他功能封装到Libredis.so中,对Libredis.so实现动态热加载,每次版本升级实现热升级,不必再进行主库切换,极大地降低运维复杂度和业务风险。 总结一下,在探索期:以业务和运维驱动为主对Redis进行定制化改造,参考MySQL的Binlog机制进行数据同步,使得主库和从库一致性得到保障。在此之后微博Redis的改造全部基于该版本。  发展期:争奇斗艳 从下图可以看出,随着时间的发展,微博在逐渐向Redis上转移业务,从13年到14年经历了巨大的服务和产品线的提升,进而带了一些特殊的需求。 微博中最为重要的是关系类存储,其量达到千亿级别,将其存储在Redis中,势必会导致日益增长的关系类存储容量问题同成本之间的矛盾(常用的Redis的型号是128G);第二点微博中琳琅满目的技术类场景需要专门的解决方案;第三是判断类的需求,利用Redis进行判断时不仅具有较大的时延还需要占据大量的内存。 针对上述需求,微博对Redis进行了定制化的改造。 针对千亿级别的关系类存储,为了减少成本,定位从Storage变为Cache;放弃了原生的Hash结构(比较占内存),定制Longset数据结构(固定长度开放寻址的Hash数组);当 Cache miss之后,Client批量为O(1),同时内存占用降为原来的1/10。 针对计数类需求,根据业务场景将KV改为定长KV;采用Double hash解决冲突。由于其用于计数场景,因此将Redis中其他数据结构从Redis cont版本中剥离,变成一个超级精简的Redis,通过预分配内存,降低指针开销。通过上述操作不仅降低了成本,同时内存占用率降为原来的1/4。 微博目前拥有十亿多用户,每个用户都有粉丝数、关注数、博文数,十亿用户至少需要三十亿的计数,这是一个相当大的开销,这就需要对Redis进一步改造:通过Schema支持多列存计数,降低了内存占用,减少了网络开销;第二点,由于计数较小较快,完全使用内存会导致资源浪费,因此可以进行冷热数据分离,热数据放在内存里,冷数据放到SSD磁盘中;当为了便于读取冷数据,增加了LRU cache模块,保证冷数据的性能;此外,再改版之后Redis中还添加了异步IO线程访问磁盘,避免性能问题。 针对判断类需求,通过Bloomfilter,采用0110的方式很简单地进行判断,极大地降低了存储空间,同时也减少时延消耗,解决了微博上是否赞过等场景的高并发问题和成本问题。 稳定期:拾遗补缺 经过四年对Redis根据业务需求不断进行改造,目前微博对Redis的使用逐步到达稳定期,主要的工作是进行查缺补漏:  服务化方面,随着业务的变大,集群规模也随之增大,拼写Hash规则已经变成负担,并且每次变更扩容都变得及其复杂;  数据流动方面,多个存储的更新存在数据不一致的情况,并且业务双写也增加了程序的复杂性;  数据迁移方面,原有的Redis的拆分和改造都需要DBA和RD共同参与以便保证数据的一致性以及尽量降低对业务的冲击。 针对上述需求,微博自研了中间件实现路由功能;在架构右侧引入Configer Service模块,统一配置管理;同时引入Slot设计,实现动态的Slot迁移,对业务无影响,此外还架构中基于Slot设计无缝扩容功能,实现线性扩容,由于架构中具有Slot Manger、Remote Proxy、Configer Service以及iTransfor中间件,架构可以融入HA等运维机制。 在微博实际关注场景中,例如我关注了你,之后需要加入你的粉丝列表;需要更新我的关注列表;还要增加两人的计数器,一个操作带来很多的入库操作。最开始采用的是程序多写的方式,但随着工程量的增加,这种操作会带来很多隐患。目前微博通过自研的DataBus,基于MySQL的row格式binlog日志实现消息的流转,保障了数据的一致性;下游兼容Redis、HBase等存储;此外,用户可自定义DataBus中的transforemer模块,支持对MySQL消息的自定义处理规则处理。 最近微博对Redis 进行了iTranstor操作。当Redis达到物理机极限时,需要对Redis进行拆分,微博自研了iTranstor,实现对单端口的Redis实现拆分;其中用户可自定义拆分规则(作为独立组件或称为Redis的一个功能),可以实现Rang或者Hash的拆分规则,实现上下游不同的Redis分支。 总结和未来 微博在使用Redis的过程中,秉承着业务驱动的模式,所有技术上的改造都是为了满足不同的业务需求;反过来技术的变革也推进了业务形态的变化,两者相互作用,呈螺旋上升的趋势。 目前,各大公司对Redis的使用已经处于相对平稳的状态。未来,Redis结合SSD等硬盘会成为下一次的爆发点吗?让我们拭目以待。
文章
存储 · NoSQL · 关系型数据库 · MySQL · Redis · 运维 · 数据库 · 固态存储 · 中间件 · 云栖大会
2016-11-02
...
跳转至:
阿里云数据库
86019 人关注 | 286 讨论 | 2692 内容
+ 订阅
  • 对话阿里云李飞飞:下一代企业级数据库6大技术方向
  • 技术解读 | PolarDB-X 强一致分布式事务
  • 【七天深入MySQL实战营】答疑汇总Day7 MySQL分支 - AliSQL 的性能优化实战
查看更多 >
开发与运维
3575 人关注 | 91249 讨论 | 87618 内容
+ 订阅
  • 如何为开源技术项目做单元测试
  • 阿里云企业级云网络解决方案,助力企业构建安全可靠的云网络
  • 【Serverless训练营】Serverless 云计算的下一个十年
查看更多 >
数据库
87761 人关注 | 33904 讨论 | 27226 内容
+ 订阅
  • 短连接访问Redis报错Cannot assign requested address解决方案
  • 对话阿里云李飞飞:下一代企业级数据库6大技术方向
  • 如何做好性能压测(一)丨压测环境设计和搭建
查看更多 >
人工智能
1899 人关注 | 7199 讨论 | 33069 内容
+ 订阅
  • 阿里面试真题详解:两数和-小于或等于目标值
  • [leetcode/lintcode 题解] 算法面试真题详解:程序检查
  • 如何做好性能压测(一)丨压测环境设计和搭建
查看更多 >
云计算
20505 人关注 | 54642 讨论 | 17228 内容
+ 订阅
  • 重磅发布!数智菩提树 磐石卷第一 信息系统基础全景图
  • 阿里云企业级云网络解决方案,助力企业构建安全可靠的云网络
  • 【Serverless训练营】Serverless 云计算的下一个十年
查看更多 >