详解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 相关文章推荐
redis配置文件中常用配置详解
Apr 14 Redis
Redis安装启动及常见数据类型
Apr 14 Redis
Redis6.0搭建集群Redis-cluster的方法
May 08 Redis
基于Redis位图实现用户签到功能
May 08 Redis
基于Redis实现分布式锁的方法(lua脚本版)
May 12 Redis
Redis延迟队列和分布式延迟队列的简答实现
May 13 Redis
Redis 配置文件重要属性的具体使用
May 20 Redis
浅谈Redis中的RDB快照
Jun 29 Redis
redis不能访问本机真实ip地址的解决方案
Jul 07 Redis
Spring Boot实战解决高并发数据入库之 Redis 缓存+MySQL 批量入库问题
Feb 12 Redis
Redis调用Lua脚本及使用场景快速掌握
Mar 16 Redis
Redis高并发缓存架构性能优化
May 15 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基础知识回顾
2012/08/16 PHP
解析thinkphp的左右值无限分类
2013/06/20 PHP
php线性表的入栈与出栈实例分析
2015/06/12 PHP
php生成二维码
2015/08/10 PHP
PHP实现163邮箱自动发送邮件
2016/03/29 PHP
简单概括PHP的字符串中单引号与双引号的区别
2016/05/07 PHP
PHP实现文件上传后台处理脚本
2020/03/04 PHP
js+xml生成级联下拉框代码
2012/07/24 Javascript
JavaScript sub方法入门实例(把字符串显示为下标)
2014/10/17 Javascript
JavaScript中的比较操作符&gt;、=、
2014/12/31 Javascript
jQuery自定义添加&quot;$&quot;与解决&quot;$&quot;冲突的方法
2015/01/19 Javascript
JavaScript基于ajax编辑信息用法实例
2015/07/15 Javascript
jQuery实现仿腾讯迷你首页选项卡效果代码
2015/09/17 Javascript
js选项卡的制作方法
2017/01/23 Javascript
Angular 4.x中表单Reactive Forms详解
2017/04/25 Javascript
深入理解react-router@4.0 使用和源码解析
2017/05/23 Javascript
详解React+Koa实现服务端渲染(SSR)
2018/05/23 Javascript
教你如何编写Vue.js的单元测试的方法
2018/10/17 Javascript
使用vue-router在Vue页面之间传递数据的方法
2019/07/15 Javascript
js实现漂亮的星空背景
2019/11/01 Javascript
Javascript如何递归遍历本地文件夹
2020/08/06 Javascript
vue 根据选择的月份动态展示日期对应的星期几
2021/02/06 Vue.js
[03:09]2014DOTA2国际邀请赛 Mushi前队友送上祝福
2014/07/12 DOTA
[02:28]PWL开团时刻DAY3——Ink Ice与DeMonsTer之间的勾心斗角
2020/11/03 DOTA
[45:17]DOTA2-DPC中国联赛定级赛 Phoenix vs DLG BO3第三场 1月9日
2021/03/11 DOTA
[55:39]DOTA2-DPC中国联赛 正赛 VG vs LBZS BO3 第二场 1月19日
2021/03/11 DOTA
解决Python出现_warn_unsafe_extraction问题的方法
2016/03/24 Python
pip matplotlib报错equired packages can not be built解决
2018/01/06 Python
Django REST framework内置路由用法
2019/07/26 Python
python 画函数曲线示例
2019/12/04 Python
Pytorch根据layers的name冻结训练方式
2020/01/06 Python
Python3+selenium实现cookie免密登录的示例代码
2020/03/18 Python
描述Cookie和Session的作用,区别和各自的应用范围,Session工作原理
2015/03/25 面试题
在校硕士自我鉴定
2014/01/23 职场文书
2014年最新版离婚协议书范本
2014/11/25 职场文书
MySQL系列之十二 备份与恢复
2021/07/02 MySQL