详解redis在微服务领域的贡献


Posted in Redis onOctober 16, 2021

前言

说到redis,可能大家的脑海中蹦出的关键词是:NoSQL、KV、高性能、缓存等。但今天的文章从另一个角度——微服务来展开。

这篇文章的起因也是源自一次面试经历,在面试一位来自陌陌的候选人(就是那个交友的陌陌)时,他提到一点让我觉得很有意思,他说redis在陌陌被使用的非常广泛,除了常规的缓存外,某些场景下也当NoSQL数据库来使用,还用redis作为微服务的注册中心,甚至连RPC的调用协议都用了redis协议。

注册中心

最早了解到redis可以作为注册中心是从dubbo的源码中看到,但一直也没有过多的了解,因为从没听说哪家公司使用redis来做服务发现。

在dubbo中使用redis来做服务发现还是挺简单的,引入jedis依赖,将注册中心地址改为redis地址即可:

<dependency>
	<groupId>redis.clients</groupId>
	<artifactId>jedis</artifactId>
	<version>2.9.0</version>
</dependency>

dubbo.registry.address=redis://127.0.0.1:6379

注册上来的数据是这样,类型是hash

/dubbo/${service}/${category}

/dubbo/com.newboo.sample.api.DemoService/consumers
/dubbo/com.newboo.sample.api.DemoService/providers

hash数据结构下保存的key是注册上来的url,value是过期时间

127.0.0.1:6379> hgetall /dubbo/com.newboo.sample.api.DemoService/providers
1) "dubbo://172.23.233.142:20881/com.newboo.sample.api.DemoService?anyhost=true&application=boot-samples-dubbo&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=com.newboo.sample.api.DemoService&metadata-type=remote&methods=sayHello&pid=19807&release=2.7.8&side=provider&timestamp=1621857955355"
2) "1621858734778"

从理论上来说,注册中心只要符合数据存储、监听推送变更、心跳检测这几个基本的功能即可。

以dubbo为例看下redis是如何利用自身特性来完成注册中心的功能( 以dubbo 2.7.8版本为例):

服务注册

  • provider在服务注册时,将服务提供方的url写入/dubbo/${service}/providers下,数据类型为hash,key为提供方url,value为key的过期时间,默认为60s,可配置
  • 写入完成后以/dubbo/${service}/providers为key调用publish命令发布一个register事件provider在初始化时起一个单独的线程每隔1/2过期时间(默认30s)时对
  • provider进行重新重新注册并发布register事件

服务发现

  • 获取匹配/dubbo/${service}/*的key(此处用到了keys命令),拿到的有这几种:/dubbo/${service}/providers/dubbo/${service}/routers/dubbo/${service}/configuators
  • /dubbo/${service}/*拿到的key进行hgetall,拿到真实的provider列表以及配置等数据,进行组装、匹配
  • 同时对每个subscribe的服务单独开一个线程,对/dubbo/${service}执行psubscribe命令阻塞等待有事件发生

详解redis在微服务领域的贡献

从源码和测试来看,dubbo的redis注册中心不能直接用于生产环境,原因有如下两点:

  • 使用了keys命令,会阻塞单线程的redis,keys执行期间,其他命令都得排队
  • 没有心跳检测这个功能,我测试了provider被kill -9杀死后,consumer是无法感知的。但从实现上来看是想通过存储的过期时间来判断服务是否可用,即需要对比url对应的value与当前的时间,如果过期应被剔除,但这部分貌似没有实现完整

虽然dubbo的redis注册中心生产不可用,但这并不影响他可以构建一个生产可用的注册中心,陌陌就是个很好的例子。

RPC调用协议

redis协议作为RPC调用协议也是陌陌同学告诉我的,当时我问了他两个问题:

  • 为什么选择redis协议作为RPC调用协议
  • redis协议如何透传类似header的隐式参数

第一个问题的答案也比较出乎意料,他说是为了跨语言调用,当时觉得只有http、gRPC等协议做到了跨语言,redis协议跨语言也是第一次听说。但仔细一想,确实没毛病,现在哪个后端语言没有实现redis的客户端呢?

之所以redis协议能够做到跨语言,这也全仰仗它的设计非常简洁,易于实现,详细协议内容可以参考这个链接:

http://redisdoc.com/topic/protocol.html

我就举一个例子来证明redis协议简洁到了什么程度,这是我很久之前就关注的一个项目

https://github.com/jdp/redisent

它是一个php实现的redis客户端,只有一个php文件,共196行,这196行包含了注释,变量定义,链接建立等,真正解析协议的代码非常少,请求的编码和发送只用了17行代码,解析返回的代码只有58行!正如项目的介绍那样:simple, no-nonsense

第二个问题回答的和我的预期一致,从redis协议的层面暂时无法支持类似header的隐式参数,但陌陌的RPC框架是自研的,所以他们在框架层解决了这个问题,序列化他们选择了json,如果要透传header参数,框架将参数组装到传输体中去。

详解redis在微服务领域的贡献

遗憾的是dubbo中的redis协议实现并不完整,无法暴露redis协议,只能调用,所以测试也只能测试client连接到redis服务器进行get、set调用,意义不大。

总结

redis目前是个用途非常广泛的存储组件,虽然在微服务领域它不是主流,但这也给我们提供了一种思路,至少这条路是可以走通的。

到此这篇关于redis在微服务领域的贡献的文章就介绍到这了,更多相关redis微服务内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Redis 相关文章推荐
分布式锁为什么要选择Zookeeper而不是Redis?看完这篇你就明白了
May 21 Redis
redis不能访问本机真实ip地址的解决方案
Jul 07 Redis
Redis集群的关闭与重启操作
Jul 07 Redis
Redis字典实现、Hash键冲突及渐进式rehash详解
Sep 04 Redis
Redis三种集群模式详解
Oct 05 Redis
Redis 持久化 RDB 与 AOF的执行过程
Nov 07 Redis
Springboot/Springcloud项目集成redis进行存取的过程解析
Dec 04 Redis
解决Redis启动警告问题
Feb 24 Redis
解决linux下redis数据库overcommit_memory问题
Feb 24 Redis
redis数据结构之压缩列表
Mar 21 Redis
Redis sentinel哨兵集群的实现步骤
Jul 15 Redis
Redis配置外网可访问(redis远程连接不上)的方法
Dec 24 Redis
详解Redis在SpringBoot工程中的综合应用
Oct 16 #Redis
Redis三种集群模式详解
浅谈Redis的keys命令到底有多慢
基于Redis结合SpringBoot的秒杀案例详解
Jedis操作Redis实现模拟验证码发送功能
Sep 25 #Redis
为什么RedisCluster设计成16384个槽
使用redis生成唯一编号及原理示例详解
Sep 15 #Redis
You might like
基于PHP与XML的PDF文档生成技术
2006/10/09 PHP
.htaccess文件保护实例讲解
2011/02/06 PHP
PHP简单计算两个时间差的方法示例
2017/06/20 PHP
PHP使用PDO实现mysql防注入功能详解
2019/12/20 PHP
JavaScript获取GridView中用户点击控件的行号,列号
2009/04/14 Javascript
网页右下角弹出窗体实现代码
2014/06/05 Javascript
JS实现判断滚动条滚到页面底部并执行事件的方法
2014/12/18 Javascript
javascript实现的简单计时器
2015/07/19 Javascript
基于jQuery Ajax实现上传文件
2016/03/24 Javascript
jquery中live()方法和bind()方法区别分析
2016/06/23 Javascript
学习Javascript闭包(Closure)知识
2016/08/07 Javascript
微信小程序canvas写字板效果及实例
2017/06/15 Javascript
JS实现简单拖拽效果
2017/06/21 Javascript
一个有意思的鼠标点击文字特效jquery代码
2017/09/23 jQuery
Angularjs实现控制器之间通信方式实例总结
2018/03/27 Javascript
AngularJS自定义过滤器用法经典实例总结
2018/05/17 Javascript
在Layui中操作数据表格,给指定单元格添加事件示例
2019/10/26 Javascript
JS实现烟花爆炸效果
2020/03/10 Javascript
谈谈JavaScript中的函数
2020/09/08 Javascript
[49:21]2018DOTA2亚洲邀请赛3月30日 小组赛B组 Effect VS iG
2018/03/31 DOTA
[02:00]最后,我终于出了辉耀
2018/03/27 DOTA
python用ConfigObj读写配置文件的实现代码
2013/03/04 Python
使用pyecharts无法import Bar的解决方案
2020/04/23 Python
Python探索之爬取电商售卖信息代码示例
2017/10/27 Python
用python的requests第三方模块抓取王者荣耀所有英雄的皮肤实例
2017/12/14 Python
python装饰器简介---这一篇也许就够了(推荐)
2019/04/01 Python
pycharm工具连接mysql数据库失败问题
2020/04/01 Python
HTML5的结构和语义(1):前言
2008/10/17 HTML / CSS
浅谈HTML5 服务器推送事件(Server-sent Events)
2017/08/01 HTML / CSS
运动服饰每月订阅盒:Ellie
2018/04/29 全球购物
英国在线玫瑰专家:InterRose
2019/12/01 全球购物
What's the difference between an interface and abstract class? (接口与抽象类有什么区别)
2012/10/29 面试题
经典祝酒词大全
2015/08/12 职场文书
信息技术远程培训心得体会
2016/01/09 职场文书
严以律己学习心得体会
2016/01/13 职场文书
干部作风纪律整顿心得体会
2016/01/23 职场文书