前言

说到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×tamp=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命令阻塞等待有事件发生

从源码和测试来看,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参数,框架将参数组装到传输体中去。

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

总结

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

如果觉得本文对你有帮助,可以转发关注支持一下

为什么redis在陌陌上使用的这么广泛?当NoSQL数据库,微服务的注册中心,RPC的调用协议都能用相关推荐

  1. redis在微服务领域的贡献

    前言 说到redis,可能大家的脑海中蹦出的关键词是:NoSQL.KV.高性能.缓存等.但今天的文章从另一个角度--微服务来展开. 这篇文章的起因也是源自一次面试经历,在面试一位来自陌陌的候选人(就是 ...

  2. redis 什么是冷数据_阿里Java三面凉凉:微服务,Redis,JVM一个都搞不懂

    前言: 金九银十刚刚过去了,不知道很多小伙伴都拿到自己心仪的offer没有,我这边也收到了一个粉丝投来的消息,说看到阿里的面试真题之后人都是懵的,发现自己一窍不通,下面给大家分享我这个粉丝的经历,以及 ...

  3. 平安银行Java社招五面面经:MQ+微服务+JVM+redis(已拿offer)

    平安银行一面: 自我介绍,聊项目, 这边挺常规的,从项目入手. 解析Excel为什么用POI ? POI存在的问题? 还知道哪些解析Excel的工具吗? 你们项目中用过MQ,平时都用MQ来做什么? 你 ...

  4. [转载]陌陌上市前夜遭网易声明三宗罪:求丁磊放过唐岩

    原文地址:陌陌上市前夜遭网易声明三宗罪:求丁磊放过唐岩 作者:互联网信徒王冠雄 就在广大中国屌丝熟悉和羡慕的移动交友软件陌陌即将赴美上市前一天,陌陌CEO老东家网易来了一记神补刀----这是直取首级的 ...

  5. 企业级nosql数据库应用与实战-redis

    企业级nosql数据库应用与实战-redis 项目场景: 随着互联网2.0时代的发展,越来越多的公司更加注重用户体验和互动,这些公司的平台上会出现越来越多方便用户操作和选择的新功能,如优惠券发放.抢红 ...

  6. Redis面试连环问:集群、复制以及与其他NOSQL数据库的区别?

    欢迎关注方志朋的博客,回复"666"获面试宝典 前言 面试官问:您熟悉redis?搭建过redis集群?rediscluster底层的主从复制rdb如何工作的?-- 接下来,就是一 ...

  7. Redis 配置连接池,redisTemplate 操作多个db数据库,切换多个db,解决JedisConnectionFactory的设置连接方法过时问题。(转)

    Redis 配置连接池,redisTemplate 操作多个db数据库,切换多个db,解决JedisConnectionFactory的设置连接方法过时问题.(转) 参考文章: (1)Redis 配置 ...

  8. 【推荐】微服务分布式企业框架Springmvc+mybatis+shiro+Dubbo+ZooKeeper+Redis

    摘要: 主要定位于互联网企业架构,已内置企业信息化系统的基础功能和高效的代码生成工具,包括:系统权限组件.数据权限组件.数据字典组件.核心工具 组件.视图操作组件.工作流组件.代码生成等.采用分层设计 ...

  9. Linux实战教学笔记45:NoSQL数据库之redis持久化存储(一)

    第1章 redis存储系统 1.1 redis概述 REmote DIctionary Server(Redis)是一个基于key-value键值对的持久化数据库存储系统.redis和大名鼎鼎的Mem ...

最新文章

  1. linux怎么添加ubuntu源,ubuntu/linuxmint如何添加和删除PPA源
  2. 扔掉Swagger,试试这款功能强大,零注解侵入的API接口文档生成工具!
  3. 2014年中回首与展望
  4. thttpd+php 不加载php.ini 问题
  5. ros创建功能包和编译过程问题处理
  6. 基于汇编语言的电子琴设计(1)
  7. Mac下安装MariaDB(自用备忘)
  8. 【JLOI2013】地形生成
  9. Java 关于中文乱码处理的经验总结
  10. mysql 学习笔记03 常用数据类型
  11. edHat linux光盘引导,[原]个性化Linux发行版光盘之补充——XZ(LZMA算法)
  12. IDEA创建包含多个module的Maven工程
  13. jquery 父元素相邻元素_Jquery中几种查找节点的方法
  14. 支付宝集五福下周一开始;iPhone 面世 13 周年;Laravel 6.10.0 发布 | 极客头条
  15. linux对文件属性及权限操作的一些基本命令
  16. 运行uiautomatorviewer.bat报错No suitable Java found
  17. 昵图网源码php,【PHP】仿我图,千图,昵图网素材下载,素材销售平台最新宽屏商业版:含新版vip会员中心,全开源...
  18. python 自动发邮件模块抄送_Python实现自动发送邮件
  19. 【备忘】零基础学习java学习路线,从菜鸟到大牛的视频教程
  20. HYPERLEDGER FABRIC网络搭建之network e2ecli_default not found

热门文章

  1. 做一个简单的学生成绩查询web系统
  2. WDA-文档-基础篇/进阶篇/讨论篇
  3. python如何实现人工智能应用_Python人工智能之初识接口
  4. Access denied的解决
  5. A Scab Grows On Wall Street
  6. 【无标题】活期储蓄帐目管理系统问题
  7. 历史地理教室-数字化地理学科教室整体解决方案
  8. 内存溢出的几种原因和解决办法
  9. Windows 下如何杀死进程
  10. 79.纯 CSS 创作单元素麦当劳金拱门 Logo(原文)