这些年,我们一起追过的缓存数据库

时间:2022-10-09 14:53:28 | 浏览:414

人生不过如此,且行且珍惜。自己永远是自己的主角,不要总在别人的戏剧里充当着配角。我以林语堂的《人生不过如此》中一句话来开篇。背景在互联网高速发展、快速演化的时代,想必在你的系统架构设计中,缓存服务是不是已经成为必不可少的一层,丰富的数据结构


人生不过如此,且行且珍惜。自己永远是自己的主角,不要总在别人的戏剧里充当着配角。

我以林语堂的《人生不过如此》中一句话来开篇。

背景

在互联网高速发展、快速演化的时代,想必在你的系统架构设计中,缓存服务是不是已经成为必不可少的一层,丰富的数据结构、高性能的读写、简单的协议,让缓存数据库很好的承担起关系型数据库的上层。畅途网为了解决节假日或高峰期的车次查询、抢票等大数据量的访问请求,很早以前就引进了 Redis,来作为数据库的上游缓存层,缓解底层数据库的读写压力。

REDIS HA 架构

世界上唯一可以不劳而获的就是贫穷,唯一可以无中生有的是梦想。没有哪件事,不动手就可以实现。世界虽然残酷,但只要你愿意走,总会有路;看不到美好,是因为你没有坚持走下去。人生贵在行动,迟疑不决时,不妨先迈出小小一步。前进不必遗憾,若是美好,叫做精彩;若是糟糕,叫做经历。**——林语堂《人生不过如此》

2014 年 10 月,为了避免单点故障,我们尝试在生产环境的 Redis 主从架构中,引入了 Redis Sentinel,实现了 Redis 服务的 failover。当 Redis-Master 主机异常宕机或 Redis-Master 服务异常崩溃时,原有的 Redis-Slave 自动升级为 master 角色,当原有 Redis-Master 恢复后,自动恢复为 slave 角色。

由于 Redis Sentinel 只能做到 Redis 服务级别的切换,无法做到 IP 地址的切换,无法完全满足现网系统架构的需要,我们又尝试在 HA 架构中加入了负载均衡器设备,引用了浮动 IP,所有应用程序访问浮动 IP,IP 地址的切换操作由负载均衡器设备来实现。


Redis Sentinel 配置文件


测试小结:

主 Redis 服务器:redis-sent-0-17

从 Redis 服务器:redis-sent-0-18

域名
redis-sent.cache.changtu.pvt

    重启 redis-sent-0-17 节点,60 秒后,redis-sent-0-18 节点成为 master,用户访问 redis-sent.cache.changtu.pvt 域名 redis 服务恢复正常,2 分钟后,redis-sent-0-17 节点重启完成,自动成为 slave;

    重启 redis-sent-0-18 节点,60 秒后,redis-sent-0-17 节点成为 master,用户访问 redis-sent.cache.changtu.pvt 域名 redis 服务恢复正常,2 分钟后,redis-sent-0-18 节点重启完成,自动成为 slave。

对应用程序的要求

    缓存应用服务统一通过域名访问。

    缓存应用服务对 Redis 域名的访问有断点重连的功能。

2015 年新增 2 台 Redis Sentinel 服务器,负责平台所有 Redis 服务器集群管理。并对平台现有 Redis 服务进行改造,逐步升级为 Redis HA 架构。

CODIS 分布式集群

你可以一辈子不登山,但你心中一定要有座山。它使你总往高处爬,它使你总有个奋斗的方向,它使你任何一刻抬起头,都能看到自己的希望。——林语堂《人生不过如此》

随着畅途网业务量上涨,数据量猛增,单点的 Redis 容量受限于服务器的内存,Redis 主从架构已经力不从心了。在业务系统对性能要求逐渐提高情况下,我们更希望将数据能存在内存中,本地持久化,而不希望写入数据库中。虽然当时用 SSD 将内存换成磁盘,以获取更大的容量,但是我们更想如何将 redis 变成一个可以水平扩展的分布式缓存服务?

在 Codis 发布之前,业界只有 Twemproxy,Twemproxy 本身是一个静态的分布式 Redis 方案,进行扩容、缩容对运维要求非常高,而且很难做到平滑的扩缩容。Codis 的目标就是尽量兼容 Twemproxy,并且加上数据迁移的功能以实现扩容和缩容,最终替换 Twemproxy。本文省略了对 Twemproxy 的介绍。

REDIS-CLUSTER

与 Codis 同时期发布的官方 redis-cluster,采用 P2P 的模式,完全去中心化架构, 其实我们花了大精力研究测试过,由于当时对 failover 判断方式提出怀疑,高耦合的模块设计思想、客户端问题、不太友好的维护等方面, 我司目前没有投入生产,没有了实际的生产维护经验,我先不发表看法。抱拳,我知道在缓存数据库里最不应该缺少的就是 Redis-cluster 了,以后有机会单独介绍吧!


容我感叹一下,别指望所有的人都能懂你,因为萝卜白菜,各有所爱。你做了萝卜,自然就做不成青菜。

好了,回归正题,先简单介绍一下 Codis,由豌豆荚于 2014 年 11 月开源,基于 Go 和 C 开发,引用作者的一段原话, Codis 采用一层无状态的 proxy 层,将分布式逻辑写在 proxy 上,底层的存储引擎是 Redis,数据的分布状态存储于 zookeeper(etcd) 中,底层的数据存储变成了可插拔的部件。各个部件是可以动态水平扩展的,尤其无状态的 proxy 对于动态的负载均衡,对业务而言完全是透明的。*


核心组件说明

1. ZooKeeper:

用来存放数据路由表和 Codis-proxy 节点的元信息,Codis-config 发起的命令都会通过 ZooKeeper 同步到各个存活的 Codis-proxy 中。

2. Codis-Proxy :

是客户端连接的 Redis 代理服务,本身是没状态的,Codis-proxy 实现了 Redis 协议,对于一个业务来说,可以部署多个 Codis-proxy, 提供连接集群 Redis 服务的入口。

3. Codis-Config :

是 Codis 的集成管理工具,支持添加 / 删除 Redis 节点、添加 / 删除 Proxy 节点、以及发起数据迁移等操作,Codis-config 还自带了 http server,会启动 dashboard,用户可以在 WEB 上监控 Codis 集群的状态。

4. Codis-Server:

是 Codis 项目维护的一个 Redis 分支,基于 redis-2.8.21 分支开发,增加了额外的数据结构,以支持 slot 有关的操作以及数据迁移指令。

5.Pre-Sharding 技术

Codis 采用 Pre-Sharding 的技术来实现数据的分片, 默认分成 1024 个 slots (0-1023), 对于每个 key 来说, 通过以下公式确定所属的 Slot Id : SlotId = crc32(key) % 1024,每一个 slot 都会有一个特定的 server group id 来表示这个 slot 的数据由哪个 server group 来提供。

在 2016 年 6 月左右,我们引进了 Codis(当时版本是 3.0,并没有 Redis-Sentinel、Codis-fe 等组件,1 年后,才升级到 3.2 的,文章主要以 3.0 版本为背景),首先介绍一下基础环境。


系统架构

在公司硬件资源有限条件下,我们计划用 6 台服务器部署 Codis,简单分了两层,Codis-Proxy 层和 Codis-Server 层。

    Codis-Proxy 层用了三台配置相对较低服务器,部署了 ZooKeeper、Codis-Proxy、Keepalived、LVS 等 ,3 个节点都做了负载均衡。

    Codis-Server 层用来三台配置相对较高的服务器,并用 SSD,3 个 Codis-group,每个 group 有一主一从,交叉部署,每个主从分配 30G 内存。



我们分别通过 jredis 编写测试程序和使用 redis-benchmark 工具模拟压力测试(请求量:1000 万~1 亿,并发数:1000~50000,长度:固定 / 可变):

    在性能方面:基本上能达到我们的预期,理想情况 Codis 性能值能达到 50~60K OP/S,各个 codis-group 中 master-slave 实例数据能实时同步,详情可以参考《Codis 高可用集群性能测试报告 _20160315》。

    数据一致性问题:一方面,Codis 的 HA 并不能保证数据完全不丢失,由于 M-S 是异步复制,当 master 节点异常或崩溃,将 slave 切换成 master 后,刚刚没来得及同步的数据就会丢失。另一方面,Codis 支持的 mget/mset 命令是无法保证单点时的原子语义的,如果 mset 指定 KEY 分布在不同 slot 上,从而导致 KEY 在不同机器上,造成要不一起成功,不要一起失败。所以对于分布式事务的问题,这是一个痛点。在实际场景中,也有人使用了 lua 脚本以扩展 Redis 的功能,虽然 Codis 支持,但是并不保证你的脚本操作的数据是否在正确的节点执行,仅仅起到一个转发功能。如果你并不能保证 lua 操作的 KEY 是否在同一个机器上,Codis 只能将这个脚本分配到参数列表中的第一个 key 的机器上执行。

    不支持命令列表,参考

    https://github.com/CodisLabs/codis/blob/release3.2/doc/unsupported_cmds.md

    Redis 修改部分(增加若干指令),参考

    https://github.com/CodisLabs/codis/blob/release3.2/doc/redis_change_zh.md

倔强的青铜

于是组织研发同事进行多次分析讨论,并提出了对缓存服务进行接口改造,经过 2 个多月的辛劳,取得了很大进展,让我们 Codis 项目顺利上线迈开了重要一步,打断一下,容我在此特别感谢一下同事王慧,在他的主导下,完成公司绝大部分缓存服务接口改造工作。

几点改造思路

1. 缓存服务分类。

    针对业务缓存服务不容许数据丢失,在现有的逻辑中,Codis 和数据库都会保留,优先从 Codis 读取,如读取不到时,会从后端数据库里读取。

    针对车次、合作方缓存服务,由于数据量大,拉取频率高的数据,只会从 Codis 里读取。

2. 对缓存服务进行接口改造,新增基础缓存服务层,将生产的 Redis/Codis 相关的服务纳入基础缓存服务进行统一管理。


    制定一套标准 KEY 命名、管理规范,包括数据类型的选择、长度、过期时间等。我们会统一在后台管理系统公示,限定新数据的规则,限制一切不合规范的行为。

    在基础缓存服务层,对部分 Codis 不支持的命令进行改写,规范 Redis/Codis 日常操作。

    统计热点数据,维护热点数据,在基础缓存服务层上假设二级缓存,作为热点数据的快速通道。

3.SLOT 的分配

哈希算法

Codis 采用 Pre-sharding 的技术来实现数据的分片, 默认分成 1024 个 slots (0-1023), 对于每个 key 来说, 通过以下公式确定所属的 Slot Id : SlotId = crc32(key) % 1024。例如 pub_cty_ct018 根据算法得出的值是 997。


key 值重定向分配

比如你有一个脚本是操作某个用户的多个信息,如 uid1age,uid1sex,uid1name 形如此类的 key,如果你不用 hashtag 的话,这些 key 可能会分散在不同的机器上,如果使用了 hashtag(用花括号扩住计算 hash 的区域):{uid1}age,{uid1}sex,{uid1}name,这样就保证这些 key 分布在同一个机器上。这个是 twemproxy 引入的一个语法,我们这边也支持了。

以 pub_cty 为例,通过 crc32hash 算法得出,key 存放在 237 slot 中,类似测试了{pub_cty}_ct01,{pub_cty}_ct02…{pub_cty}_ctnn 都存放在 237 slot 中。第一,有了 hashtag 算法支持,我们可以对特定需求的 key 做一些特需的规划,将这些特殊的 key 有序的存放在 codis slot 中,保证 mget/mset, 以及 lua 脚本正常执行。我们目前大概管理 200 多个 redis 键,统一锁定到一个 codis-server(slot)中。第二,在某些极端情况(不希望发生),如某 codis-group 中的 master 异常或崩溃时,我们从程序设计角度,尽可能对出现的无法进行操作 KEY 的行为做一些 " 某种意义上 " 保护。譬如,当某 codis-group 的 maser 宕机时,对 codis 进行写操作,如果对应的 key 落到宕机的主机上,会得到异常或者错误,可以通过捕获异常信息,将异常的 key 通过改变 key 名的规则将其存放到其他 codis-group 上。同理,如果是读取宕机主机上的 key 数据时,将其引导到调整后的 key 上,在一定程度上保障 codis 的完整性(不保障数据不丢失,只保证业务系统操作缓存数据完整性)。

有点意思的整改

在长达几年的迭代演变过程中,维护团队推动多次缓存服务架构的升级与优化,缓存服务逐渐完善和稳定。 记下了一些“有点意思”的整改,提供大家参考。

热点数据

统计缓存热点数据,在基础缓存服务层上假设二级缓存,作为热点数据的快速通道,具备可动态获取,最快访问,少变化的特点 。

根据缓存服务各主、子键关系,使用 index_{主键}的方式来作为管理主子键关系的 SortedSet 集合,统计数据的使用频率,抽取 Top100 的数据,作为热点数据。对这批数据进行分析,结合数据的改动频率,制定这批数据缓存在内存中的时长。


二级缓存设计

缓存数据列表生成与维护

内存缓存数据的 key 列表由缓存服务生成和维护,Key 列表包括后台手动配置(如,10 个)和系统根据使用热度生成(如,20 个)共同组成,其中 cache-manager 的 jar 包只负责对该数据使用,通过定时任务获取 codis 中的前 20 位和后台手动配置的相关数据,期间要保证获取到数据的有效性。


维护本地内存中的数据

自然统计内存缓存: 用 sortedSet 集合,统计各主键下的所有键 Get 的次数,汇总成 score_{主键}方式的集合。利用 ZIncrby 命令统计对应的子键的次数,最终汇总每个主键,统计出 Top100 的 key,利用 zunionstore 命令将信息统计汇总作为内存缓存的基础,此集合内数据均从内存中获取。

管理类内存缓存: 分析和统计项目主流程的关键的基础缓存数据保存到内存中, 保障对应区域的数据获取与缓存时间,在离开数据源后能够最大程度的展现畅途网的功能。

在发生手动更新时,对内存中对应的主键进行更新

在发生更新时,由后台发起,在缓存服务向 codis 中置入标志位,各客户端在定时任务中获取标志位,如果标志位(cache_memory_update_flag)为 Y,则清空内存和 Key 规则表,等到下一个更新周期来临重新获取数据。

总结

多年后,再回想年少时的迷茫和执著,或许原因都记不得了。青春就是让你张扬的笑,也给你莫名的痛。——林语堂《人生不过如此》

经过大半年的时间测试、缓存服务接口改造,在 2016 年 9 月份,赶在国庆前,我们的 Codis3.0 上线了,在车次查询等方面,有了质的飞越,尤其节假日或高峰期期间,平滑的扩缩容、数据迁移、高可用等方面展示出巨大优势。


三个 codis_proxy 节点的均衡情况:

1 年后,2018 年 8~9 月份,我们将 Codis 升级到 3.2 的,由之前 6 台服务器,扩展到 7 台,实际上多一台 Codis-web 节点,独立承担 Codis-fe、Codis-dashboard 等组件。对于 Redis-Sentinel、Codis-fe 等组件的引进,解决了运维人员很多问题,在此不再描述,有兴趣的可以参考。

https://github.com/CodisLabs/codis/blob/3.2.2/doc/tutorial_zh.md


目前 Codis 作为畅途网最为核心的缓存层,一如既往的稳定输出,肩负起它的神圣使命!

相关资讯

数据告诉你,澳门旅游最受哪些人欢迎?

新华社北京12月16日电(记者高洁)澳门回归祖国20年来,旅游业及相关餐饮、酒店、会展业迅速发展。特别是2003年开放内地居民赴澳个人游后,澳门经济活力更加旺盛。飞猪平台数据显示,近三年来澳门的游客数劲增,年均增长约75%。截至2019年1

云南曲靖市沾益区统计数据严重失实,多名干部、多家企业被处理

新京报快讯 据“清风云南”消息,云南省纪委省监委对省统计局移送的曲靖市沾益区统计违纪违法相关问题线索,进行了认真调查核实。经查,曲靖市沾益区规模以上工业和固定资产投资统计数据严重失实,被抽查的29家规模以上工业企业总产值和15个项目固定资产

洞察未来,你想象不到“大数据雅安”有多牛X!

这里是地球·世界·中国·四川·雅安Earth— World— China— Sichuan— Ya"an当下,生活因为大数据而变得更加快捷、高效如今,大数据正在改变着人们的生活方式以前车马很慢书信很远现在生活快到大数据可以告诉我们一切可以让

四川十强县数据对比,谁是四川第一县呢?

根据2020年四川各区县市的GDP统计情况,四川各区县市经济表现平稳。四川共有183个县域,其中市辖区55个、县级市19个、县109个,下面我们根据GDP的高低为四川排名十强县(此名单不含市辖区和县级市)2020年四川GDP总量前十强县名单

数据显示国庆假期海南十大客源地:上海预订量最高四川预订增速最快

新海南客户端、南海网、南国都市报9月24日消息(记者 苏靓)自9月中旬,三亚市解除全域临时静态管理以来,三亚旅游业的利好消息频传,9月21日晚,“三亚市旅游景区有序恢复开放”的消息,再次释放政策利好。随着三亚疫情得到有效控制,以及相关限制逐

常住人口156.60万人!鹤壁第七次全国人口普查主要数据公布

河南日报客户端记者 陈晨 蒋晓芳 通讯员 田白雪5月27日,记者从鹤壁市统计局获悉,根据国务院第七次全国人口普查领导小组办公室反馈的数据,鹤壁市常住人口为156.60万人,城镇化率60.98%,比全省高5.55个百分点,城镇化进程加速明显。

速读报告|潍坊5年成绩单《政府工作报告》里这组数据告诉你

2022年4月13日,潍坊市召开第十八届人民代表大会第一次会议,在《政府工作报告》中,一组数据告诉你,五年来,潍坊有多拼。——这五年,综合实力显著提升。地区生产总值跃上7000亿元台阶,达到7010.6亿元,居全国大中城市第35位。一般公共

产品经理的技术修行笔记——数据库篇

产品经理在产品功能设计,尤其是平台类产品设计的过程中,必然涉及到数据模型以及数据操作相关的设计。在用户场景和功能层面来看,是一个个根据用户的使用场景设计的功能点。但是从数据层面来看,是根据用户在该场景内对产品输入的数据信息进行处理并输出结果

数据库行业深度报告:历史机遇,国产数据库市场迎来十倍空间

获取报告请登录未来智库www.vzkoo.com。一、数据库行业的基本情况(略)1.数据库的性能:六个方面,一套标准数据库的性能指标聚焦于 6 个方面:吞吐量、负载均衡、读写速度、分区分片、并发性和 可用性。不同类型的数据库由于使用场景的差

AI+大数据赋能精准营销和智能风控百融云创助推金融数字化转型

“十三五”以来,伴随新一代信息技术的快速演进,推动数字经济不断发展壮大,使得消费互联、产业互联与金融服务更紧密结合,线上化、数字化、智能化的“非接触服务”逐渐普及。特别是在新冠肺炎疫情倒逼之下,我国金融业积极谋变,数字化转型进程明显加快。提

友情链接

天天财经元宇宙中国SEO域名抢注宝宝起名网网站监控阿姆斯特丹旅游网自行车之家世纪数藏NFT保健品排名网理财投资网南京交友相亲网吉林旅游网邵阳新闻头条网UFO飞碟探索网张家界旅游网辽宁旅游网今日淮北红星二锅头股票网美食菜谱网西安旅游攻略网汕尾新闻资讯网民谣吉他网南宁AI智能引流系统生鲜电商网韦尔股份A股NFT数字藏品平台大全今日东营安顺头条新闻网永州新闻头条网海口新闻头条网许昌新闻头条网孝感新闻头条网南宁新闻资讯网月子餐食谱网珠海头条新闻网
MYSQL数据库应用网-mysql数据库基础知识、Mysql还原数据库、mysql数据库迁移方案、mysql数据库增删改查、mysql数据备份和恢复、mysql数据迁移工具、mysql数据库迁移详细步骤、mysql数据库存储目录迁移、mysql数据库不停机迁移方法、mysql数据备份和恢复、免费mysql服务器、mysql官网免费版安装教程。
MySQL数据库应用 nincu.cn©2022-2028版权所有