MySQL高速缓存——Redis

Redis

redis的介绍

什么是redis?

Redis是一个nosql(not only sql不仅仅只有sql)数据库,翻译成中文叫做非关系型型数据库。Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动分区(Cluster)提供高可用性(high availability)

redis有哪些适合的场景?

  • 热点数据的缓存
    由于redis访问速度块、支持的数据类型比较丰富,所以redis很适合用来存储热点数据,另外结合expire,我们可以设置过期时间然后再进行缓存更新操作,这个功能最为常见,几乎所有的大型项目都有所运用。

  • 限时业务的运用
    redis中可以使用expire命令设置一个键的生存时间,到时间后redis会删除它。利用这一特性可以运用在限时的优惠活动信息、手机验证码等业务场景。

  • 计数器相关问题
    redis由于incrby命令可以实现原子性的递增,所以可以运用于高并发的秒杀活动、分布式序列号的生成、具体业务还体现在比如限制一个手机号发多少条短信、一个接口一分钟限制多少请求、一个接口一天限制调用多少次等等。

  • 排行榜相关问题
    关系型数据库在排行榜方面查询速度普遍偏慢,所以可以借助redis的SortedSet进行热点数据的排序。

  • 分布式锁
    在并发进程中,我们通过锁(lock),来避免由于竞争而造成的数据不一致问题。通常,我们结合Lock的过期时间防止程序死锁。

  • 延时操作
    在用户提交订单后我们占用了库存,10分钟后去检验用户是够真正购买,如果没有购买将该单据设置无效,同时还原库存。所以我们对于上面的需求就可以用以下解决方案,我们在订单生成时,设置一个key,同时设置10分钟后过期, 我们在后台实现一个监听器,监听key的实效,监听到key失效时将后续逻辑加上。 当然我们也可以利用rabbitmq、activemq等消息中间件的延迟队列服务实现该需求。

  • 分页、模糊搜索
    redis的set集合中提供了一个zrangebylex方法, 这个方法可以返回字典区间的数据,利用这个特性可以进行模糊查询功能,这个也是目前我在redis中发现的唯一一个支持对存储内容进行模糊查询的特性。假如数据60万左右,响应时间在700ms左右,比mysql的like查询稍微快一点,但是由于它可以避免大量的数据库io操作,所以总体还是比直接mysql查询更利于系统的性能保障。

  • 点赞、好友等相互关系的存储
    Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。 又或者在微博应用中,每个用户关注的人存在一个集合中,就很容易实现求两个人的共同好友功能。

  • 队列
    由于redis有list push和list pop这样的命令,所以能够很方便的执行队列操作。

redis的安装

下载地址:https://redis.io/download
tar zxf redis-5.0.8.tar.gz
cd redis-5.0.8
make make成功后会在src文件夹下产生一些二进制可执行文件,包括redis-server、redis-cli等等
make install

cd utils/
./install_server.sh 一直回车
在这里插入图片描述
vim /etc/redis6379.conf

bind 0.0.0.0(修改端口使其他主机可以访问)

ss -antlp
/etc/init.d/redis_6379 restart 重启redis

Redis常用命令

参考官网:http://doc.redisfans.com/

Redis异步复制

在node1-3上安装redis:
vim /etc/redis/6379.conf 主从复制的开启,完全是在从节点发起的;不需要我们在主节点做任何事情。

bind 0.0.0.0
slaveof 172.25.253.1 6379

/etc/init.d/redis_6379 restart
测试:
在node1中:
redis-cli

set name test
get name

在node2和node3中redis-cli进行get name可同步查看到信息
在这里插入图片描述
也可进入redis后使用info看到slave。

Redis高可用

Redis Sentinel 为Redis提供了高可用的实现。通俗来说就是你可以部署一套无需人为干预即可防灾的Redis环境。RS同时为客户端提供了其他诸如监控,通知的功能。

  • 监控: Redis Sentinel 时刻监控主从是否在正常工作。
  • 通知: 当某个Redis实例出现问题,Redis Sentinel 可以通知系统管理员或者通过API通知其他程序。
  • 自动切换: 如果一个主实例失效,Redis Sentinel 会启动一个失效转移(从升级为主)的进程,其他的从节点将重新跟随新的主节点。连接到RedisServer的会被通知切换到新的地址。
  • 配置提供者: Redis Sentinel 充当了客户端服务自动发现的提供者:连接到Sentinal的客户端,Sentianl会响应最新的主节点地址给客户端,并且当发生转移的时候会发送通知。
    配置
    cd redis-5.0.8
    cp sentinel.conf /etc/redis/
    vim /etc/redis/sentinel.conf
修改以下三行内容:
84 sentinel monitor mymaster 172.25.10.1 6379 2
#2表示两票,至少开三个sentinel,只有指定数量的sentinel同意(主管下线)时,sentinel才会做主从切换
#这个数字一般大于sentinel数量的半数

scp /etc/redis/sentinel.conf root@172.25.253.2:/etc/redis/ 不要启动之后在复制
scp /etc/redis/sentinel.conf root@172.25.253.3:/etc/redis/

测试
redis-sentinel /etc/redis/sentinel.conf 在三个redis上分别开启监控
再开启一个shell连接node1进入redis(redis-cli)后SHUTDOWN
等待30s后,在监控页面可以看到:
在这里插入图片描述
node1宕掉后,而node3变成新的master的信息,此时node1主观下线。
重新开启node1的redis时,会自动成为server3的slave(在node1的配置文件中写入SLAVEOF 172.25.10.3 6379)

twemproxy代理分片

官方地址: https://github.com/twitter/twemproxy

Twemproxy是一种代理分片机制,由Twitter开源。Twemproxy作为代理,可接受来自多个程序的访问,按照路由规则,转发给后台的各个Redis服务器,再原路返回。该方案很好的解决了单个Redis实例承载能力的问题。当然,Twemproxy本身也是单点,需要用Keepalived做高可用方案。通过Twemproxy可以使用多台服务器来水平扩张redis服务,可以有效的避免单点故障问题。虽然使用Twemproxy需要更多的硬件资源和在redis性能有一定的损失(twitter测试约20%),但是能够提高整个系统的HA也是相当划算的。twemproxy不光可以代理redis,还可以代理memcached。

集群

解决方案

由于 Redis 出众的性能,其在众多的移动互联网企业中得到广泛的应用。Redis 在 3.0 版本前只支持单实例模式,虽然现在的服务器内存可以到 100GB、200GB 的规模,但是单实例模式限制了 Redis 没法满足业务的需求(例如新浪微博就曾经用 Redis 存储了超过 1TB 的数据)。Redis 的开发者 Antirez 早在博客上就提出在 Redis 3.0 版本中加入集群的功能,但 3.0 版本等到 2015 年才发布正式版。各大企业在 3.0 版本还没发布前为了解决 Redis 的存储瓶颈,纷纷推出了各自的 Redis 集群方案。这些方案的核心思想是把数据分片(sharding)存储在多个 Redis 实例中,每一片就是一个 Redis 实例。

下面介绍 Redis 的集群方案。

客户端分片

客户端分片是把分片的逻辑放在 Redis 客户端实现,通过 Redis 客户端预先定义好的路由规则,把对 Key 的访问转发到不同的 Redis 实例中,最后把返回结果汇集。

客户端分片的好处是所有的逻辑都是可控的,不依赖于第三方分布式中间件。开发人员清楚怎么实现分片、路由的规则,不用担心踩坑。

客户端分片方案有下面这些缺点。

  • 这是一种静态的分片方案,需要增加或者减少 Redis 实例的数量,需要手工调整分片的程序。
  • 可运维性差,集群的数据出了任何问题都需要运维人员和开发人员一起合作,减缓了解决问题的速度,增加了跨部门沟通的成本。
  • 在不同的客户端程序中,维护相同的分片逻辑成本巨大。例如,系统中有两套业务系统共用一套 Redis 集群,一套业务系统用 Java 实现,另一套业务系统用 PHP 实现。为了保证分片逻辑的一致性,在 Java 客户端中实现的分片逻辑也需要在 PHP 客户端实现一次。相同的逻辑在不同的系统中分别实现,这种设计本来就非常糟糕,而且需要耗费巨大的开发成本保证两套业务系统分片逻辑的一致性。

Twemproxy

Twemproxy 是由 Twitter 开源的 Redis 代理,其基本原理是:Redis 客户端把请求发送到 Twemproxy,Twemproxy 根据路由规则发送到正确的 Redis 实例,最后 Twemproxy 把结果汇集返回给客户端。

Twemproxy 通过引入一个代理层,将多个 Redis 实例进行统一管理,使 Redis 客户端只需要在 Twemproxy 上进行操作,而不需要关心后面有多少个 Redis 实例,从而实现了 Redis 集群。

Twemproxy 的优点如下

  • 客户端像连接 Redis 实例一样连接 Twemproxy,不需要改任何的代码逻辑。
  • 支持无效 Redis 实例的自动删除。
  • Twemproxy 与 Redis 实例保持连接,减少了客户端与 Redis 实例的连接数。

Twemproxy 有如下不足

  • 由于 Redis 客户端的每个请求都经过 Twemproxy 代理才能到达 Redis 服务器,这个过程中会产生性能损失。
  • 没有友好的监控管理后台界面,不利于运维监控。
  • 最大的问题是 Twemproxy 无法平滑地增加 Redis 实例。对于运维人员来说,当因为业务需要增加 Redis 实例时工作量非常大。

Twemproxy 作为最被广泛使用、最久经考验、稳定性最高的 Redis 代理,在业界被广泛使用。

Codis

Twemproxy 不能平滑增加 Redis 实例的问题带来了很大的不便,于是豌豆荚自主研发了 Codis,一个支持平滑增加 Redis 实例的 Redis 代理软件,其基于 Go 和 C 语言开发,并于 2014 年 11 月在 GitHub 上开源。

Codis 包含下面 4 个部分

  • Codis Proxy:Redis 客户端连接到 Redis 实例的代理,实现了 Redis 的协议,Redis 客户端连接到 Codis Proxy 进行各种操作。Codis Proxy 是无状态的,可以用 Keepalived 等负载均衡软件部署多个 Codis Proxy 实现高可用。
  • CodisRedis:Codis 项目维护的 Redis 分支,添加了 slot 和原子的数据迁移命令。Codis 上层的 Codis Proxy 和 Codisconfig 只有与这个版本的 Redis 通信才能正常运行。
  • Codisconfig:Codis 管理工具。可以执行添加删除 CodisRedis 节点、添加删除 Codis Proxy、数据迁移等操作。另外,Codisconfig 自带了 HTTP server,里面集成了一个管理界面,方便运维人员观察 Codis 集群的状态和进行相关的操作,极大提高了运维的方便性,弥补了 Twemproxy 的缺点。
  • ZooKeeper:分布式的、开源的应用程序协调服务,是 Hadoop 和 Hbase 的重要组件,其为分布式应用提供一致性服务,提供的功能包括:配置维护、名字服务、分布式同步、组服务等。Codis 依赖于 ZooKeeper 存储数据路由表的信息和 Codis Proxy 节点的元信息。另外,Codisconfig 发起的命令都会通过 ZooKeeper 同步到 CodisProxy 的节点。

Codis 引入了 Redis Server Group,其通过指定一个主 CodisRedis 和一个或多个从 CodisRedis,实现了 Redis 集群的高可用。当一个主 CodisRedis 挂掉时,Codis 不会自动把一个从 CodisRedis 提升为主 CodisRedis,这涉及数据的一致性问题(Redis 本身的数据同步是采用主从异步复制,当数据在主 CodisRedis 写入成功时,从 CodisRedis 是否已读入这个数据是没法保证的),需要管理员在管理界面上手动把从 CodisRedis 提升为主 CodisRedis。

如果觉得麻烦,豌豆荚也提供了一个工具 Codis-ha,这个工具会在检测到主 CodisRedis 挂掉的时候将其下线并提升一个从 CodisRedis 为主 CodisRedis。

Codis 中采用预分片的形式,启动的时候就创建了 1024 个 slot,1 个 slot 相当于 1 个箱子,每个箱子有固定的编号,范围是 1 ~ 1024。slot 这个箱子用作存放 Key,至于 Key 存放到哪个箱子,可以通过算法“crc32(key)%1024”获得一个数字,这个数字的范围一定是 1~1024 之间,Key 就放到这个数字对应的 slot。例如,如果某个 Key 通过算法“crc32(key)%1024”得到的数字是 5,就放到编码为 5 的 slot(箱子)。1 个 slot 只能放 1 个 Redis Server Group,不能把 1 个 slot 放到多个 Redis Server Group 中。1 个 Redis Server Group 最少可以存放 1 个 slot,最大可以存放 1024 个 slot。因此,Codis 中最多可以指定 1024 个 Redis Server Group。

Codis 最大的优势在于支持平滑增加(减少)Redis Server Group(Redis 实例),能安全、透明地迁移数据,这也是 Codis 有别于 Twemproxy 等静态分布式 Redis 解决方案的地方。Codis 增加了 Redis Server Group 后,就牵涉到 slot 的迁移问题。例如,系统有两个 Redis Server Group,Redis Server Group 和 slot 的对应关系如下。

Redis Server Groupslot
11~500
2501~1024

当增加了一个 Redis Server Group,slot 就要重新分配了。Codis 分配 slot 有两种方法。

  • 通过 Codis 管理工具 Codisconfig 手动重新分配,指定每个 Redis Server Group 所对应的 slot 的范围,例如可以指定 Redis Server Group 和 slot 的新的对应关系如下。
Redis Server Groupslot
11~500
2501~700
3701~1024
  • 第二种:通过 Codis 管理工具 Codisconfig 的 rebalance 功能,会自动根据每个 Redis Server Group 的内存对 slot 进行迁移,以实现数据的均衡。

Redis 3.0 集群

Redis 3.0 集群采用了 P2P 的模式,完全去中心化。Redis 把所有的 Key 分成了 16384 个 slot,每个 Redis 实例负责其中一部分 slot。集群中的所有信息(节点、端口、slot 等),都通过节点之间定期的数据交换而更新。

Redis 客户端在任意一个 Redis 实例发出请求,如果所需数据不在该实例中,通过重定向命令引导客户端访问所需的实例。

Redis 集群内的机器定期交换数据,工作流程如下。

  • Redis 客户端在 Redis2 实例上访问某个数据。

  • 在 Redis2 内发现这个数据是在 Redis3 这个实例中,给 Redis 客户端发送一个重定向的命令。

  • Redis 客户端收到重定向命令后,访问 Redis3 实例获取所需的数据。

Redis 3.0 的集群方案有以下两个问题。

一个 Redis 实例具备了“数据存储”和“路由重定向”,完全去中心化的设计。这带来的好处是部署非常简单,直接部署 Redis 就行,不像 Codis 有那么多的组件和依赖。但带来的问题是很难对业务进行无痛的升级,如果哪天 Redis 集群出了什么严重的 Bug,就只能回滚整个 Redis 集群。

对协议进行了较大的修改,对应的 Redis 客户端也需要升级。升级 Redis 客户端后谁能确保没有 Bug?而且对于线上已经大规模运行的业务,升级代码中的 Redis 客户端也是一个很麻烦的事情。

综合上面所述的两个问题,Redis 3.0 集群在业界并没有被大规模使用。

云服务器上的集群服务

国内的云服务器提供商阿里云、UCloud 等均推出了基于 Redis 的云存储服务。

这个服务的特性如下

  • 动态扩容:用户可以通过控制面板升级所需的 Redis 存储空间,扩容的过程中服务部不需要中断或停止,整个扩容过程对用户透明、无感知,这点是非常实用的,在前面介绍的方案中,解决 Redis 平滑扩容是个很烦琐的任务,现在按几下鼠标就能搞定,大大减少了运维的负担。
  • 数据多备:数据保存在一主一备两台机器中,其中一台机器宕机了,数据还在另外一台机器上有备份。
  • 自动容灾:主机宕机后系统能自动检测并切换到备机上,实现服务的高可用。
  • 实惠:很多情况下为了使 Redis 的性能更高,需要购买一台专门的服务器用于 Redis 的存储服务,但这样子 CPU、内存等资源就浪费了,购买 Redis 云存储服务就很好地解决了这个问题。

有了 Redis 云存储服务,能使 App 后台开发人员从烦琐运维中解放出来。App 后台要搭建一个高可用、高性能的 Redis 服务,需要投入相当的运维成本和精力。如果使用云存储服务,就没必要投入这些成本和精力,可以让 App 后台开发人员更专注于业务。

Redis集群

redis-cli --cluster create

测试:
在一个节点中插入数值,在任何节点中都可查看(若不在插入数值所在的主从中也会被重定向到数值所在的主)

再mkdir 7006 7007修改配置文件中的端口并开启节点:

将7006加入集群:
redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000

将7007作为7006的slave加入集群:
redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7000 --cluster-slave --cluster-master-id d0ba4fb6b9e627f80341c3737c2e1319cddd14dd

分配hash槽:
redis-cli --cluster reshard 127.0.0.1:7000 --cluster-from 596a60abeef8d85d96a70780e85b0f5adbd34f9f --cluster-to d0ba4fb6b9e627f80341c3737c2e1319cddd14dd --cluster-slots 1000 --cluster-yes

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值