返回顶部
首页 > 资讯 > 精选 >Java如何手写Redis服务端
  • 274
分享到

Java如何手写Redis服务端

2023-06-22 05:06:06 274人浏览 泡泡鱼
摘要

小编给大家分享一下Java如何手写Redis服务端,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!一,Redis通讯与Netty1,tcp连到Redis服务器的客户端建立了一个到6379端口的TCP连接。虽然RESP在技术上

小编给大家分享一下Java如何手写Redis服务端,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!

一,Redis通讯与Netty

1,tcp

连到Redis服务器的客户端建立了一个到6379端口的TCP连接。

虽然RESP在技术上不特定于TCP,但是在Redis的上下文中,该协议仅用于TCP连接(或类似的面向流的连接,如unix套接字)。

使用netty作为通讯框架

2,协议

Redis客户端和服务器端通信使用名为 RESP (REdis Serialization Protocol) 的协议。虽然这个协议是专门为Redis设计的,它也可以用在其它 client-server 通信模式的软件上。 RESP 协议在Redis1.2被引入,直到Redis2.0才成为和Redis服务器通信的标准。这个协议需要在你的Redis客户端实现。

RESP 是一个支持多种数据类型的序列化协议:简单字符串(Simple Strings),错误( Errors),整型( Integers), 大容量字符串(Bulk Strings)和数组(Arrays)。

RESP在Redis中作为一个请求-响应协议以如下方式使用:

客户端以大容量字符串RESP数组的方式发送命令给服务器端。 服务器端根据命令的具体实现返回某一种RESP数据类型。 在 RESP 中,数据的类型依赖于首字节:

单行字符串(Simple Strings): 响应的首字节是 "+" 错误(Errors): 响应的首字节是 "-" 整型(Integers): 响应的首字节是 ":" 多行字符串(Bulk Strings): 响应的首字节是"$" 数组(Arrays): 响应的首字节是 "*" 另外,RESP可以使用大容量字符串或者数组类型的特殊变量表示空值,下面会具体解释。RESP协议的不同部分总是以 "\r\n" (CRLF) 结束。 字符串 "foobar" 编码如下:

"$6\r\nfoobar\r\n"

实际redis命令是什么样的,比如 SET lhjljh lhjkjhkh

*3\r\n$3\r\nSET\r\n$6\r\nlhjljh\r\n$8\r\nlhjkjhkh

3,编解码

由于RESP天然是面向处理命令的,所以没办法直接把redis消息像grpc或者dubbo那样直接序列化和反序列化消息。并且每个内容限定了长度,很适合做成及时序列化、零拷贝,直接针对输入流做反序列化和序列化,这一点与Protostuff序列化协议的设计很类似。 所以序列化直接将服务端接收的流直接转成值。

Java如何手写Redis服务端

编解码的实体类直接加入redis server 的处理某一个长连接tcp客户端的管道上。

Java如何手写Redis服务端

4,命令处理

将消息解码成RESP,还需要将RESP转为Command对象,这里因为是java语言,方法与类绑定,编写上和理解上会更加容易。但是会增加一些开销。

Java如何手写Redis服务端

二,redis 的数据结构

1,底层主结构

底层主树使用跳表ConcurrentSkipListMap实现,没用hash类map的原因是服务端是集群后,客户端可能使用hash路由,会导致服务端严重的hash冲突,性能大打折扣

Java如何手写Redis服务端

key为封装的“String”,重写了equals方法避免相同的key但是在JVM中指针不同

Java如何手写Redis服务端

value是一个接口,实现类是redis的五大基本类型,所有数据类型都包含超时时间

Java如何手写Redis服务端

2,key

用封装的值做value的原因是方便统一管理

Java如何手写Redis服务端

3,list

底层使用LinkedList的原因是LinkedList实现了多种接口,实现各种命令直接调用其现成实现的方法即可

Java如何手写Redis服务端

Java如何手写Redis服务端

4,set

底层使用HashSet,redis里的set没有多特殊

Java如何手写Redis服务端

5,hash

底层使用HashMap,这里和开头说的HashMap不冲突。为什么不用跳表?压缩列表很巧妙,大抵的意思就是将通信收到的数组直接填充到list中,将list直接按照次序直接当map使用,主要是0拷贝的思想,无需创建新资源,性能极高,但注意压缩列表与压缩无关。

Java如何手写Redis服务端

6,zset

首先需要封装一个带有值和分值的对象

Java如何手写Redis服务端

再用TreeMap重写compare方法即可,使用TreeMap原因是他天然有良好的排序功能,很多hash一致路由的算法都用的TreeMap二开。

Java如何手写Redis服务端

三,redis AOF 持久化

1,aof线程与tcp线程解耦,即写缓冲

再解析redis命令时,将redis写命令添加到写aof日志的队列中

Java如何手写Redis服务端

这里自己封装了一个堵塞队列,单线程吞吐量可以达到3000W /s是LinkedBlockingQueue的6到10倍,完全可以胜任此场景

Java如何手写Redis服务端

Java如何手写Redis服务端

RingBlockingQueue吞吐量非常高的原因是使用了内存连续页的机制。

Java如何手写Redis服务端

2,aof持久化协议

aof协议一句话概括就是将写命令,追加到日志中,开始时将命令读取,当作收到网络的命令执行即可。由于协议过于简单,这里就不贴链接了。 aof之日格式如下图:

Java如何手写Redis服务端

3,aof的加载与存储实现

这里读写内存都是用的内存文件映射,好处是读写性能好,坏处是可能会出现内存泄漏,调试期间比较麻烦。

Java如何手写Redis服务端

4,内存文件映射与面向对象

这里存储和加载aof文件的代码都是面向过程的,看起来非常复杂。实际上之前是按照面向对象写的,封装成了行对象,调用落盘符和拾起方法就可以写入和读取aof中的命令,但是TPS仅为10w/s,后来权衡后改为面向过程,吞吐量提升到了100W的TPS以上。

四,redis 的集群特性

1,主从

这里很容易联想到mysql的只从,很多场景下会使用基于Mysql主从的读写分离,或者zk的主从。 但实际上redis的主从是不保证一致性的,个人认为redist的主从主要考虑的是cap的分布式容错性。 因为redis主从不保证一致性,所以使用redis读写分离,可能造成一些不一致的问题,写写是一致的,但是读是不一致的,可以根据项目需要做取舍。

2,主从复制

redis的主从复制这里作者没看懂(可能也是一致性上有坑没动力去看),所以没写出来。

3,分片集群

redis集群主要分为几个唯独: 主从、分区集群、代理。 一般在redis客户端的视角下,主要是分区集群,根据发送给redis的key做hash、md5等操作,取一个所有客户端的共识值,将key和value发送,也就是客户端路由分布式软件的集群实现方式京东的redis集群设计到redis具体一个分片。

五,redis 的压测与调优

1,aof内存泄漏

开启aof压测发现出现了内存泄漏,后来发现是频繁新建内存池而造成的,所以将内存池池化,即aof对象中仅存在一个bytebuff内存池。

2,内存复用提升性能

这里编解码没有单独开辟byte数据接收bytebuff的数据进行编解码,编解码直接读取bytebuff进行编解码,没有出现内存拷贝,唯独新建了BytesWrapper对象,但存储的数据都是使用BytesWrapper对象,对内存新建/销毁的开销很少。

3,0.05%消息延迟超200ms排查

下图为C语言版的redis压测数据:

Java如何手写Redis服务端

下图为java语言版的redis压测数据:

Java如何手写Redis服务端

4,性能表现

redis原版的性能大概是E5系列CPU 4-5w左右,上图中是使用amd芯片测试的数据。 使用redis自带的压测工具,维持100个客户端连接,java版性能是c语言原版性能的75-90%左右,性能依然强悍。

看完了这篇文章,相信你对“Java如何手写Redis服务端”有了一定的了解,如果想了解更多相关知识,欢迎关注编程网精选频道,感谢各位的阅读!

--结束END--

本文标题: Java如何手写Redis服务端

本文链接: https://lsjlt.com/news/302916.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Java如何手写Redis服务端
    小编给大家分享一下Java如何手写Redis服务端,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!一,redis通讯与Netty1,tcp连到Redis服务器的客户端建立了一个到6379端口的TCP连接。虽然RESP在技术上...
    99+
    2023-06-22
  • Java手写Redis服务端的实现
    目录零,起因一,redis通讯与Netty1,tcp2,协议3,编解码4,命令处理二,redis的数据结构1,底层主结构2,key3,list4,set5,hash6,zset三,r...
    99+
    2024-04-02
  • java重写redis服务端
    背景 最近研究了下redis的协议、持久化策略以及单线程模型,突然觉得和java很搭配。源码请用力戳这里 目的 鉴于redis是c编写,java的同学读起来比较费力,所以写java版。让更多的开发者理解高性...
    99+
    2024-04-02
  • Java中Socket如何实现Redis客户端
    小编给大家分享一下Java中Socket如何实现Redis客户端,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!Redis是最常见的缓存服务中间件,在java开发中,一般使用 jedis 来实现。Redis的命令协议:$参数...
    99+
    2023-06-15
  • java WebSocket 服务端如何实现
    这篇文章给大家分享的是有关java WebSocket 服务端如何实现的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。什么是WebSocket  WebSocket协议是基于TCP的一种新的网络...
    99+
    2023-06-29
  • java服务端如何接入WebSocket?
    日常工作中,我们都是使用http请求,来进行前后交互,那么我们也会有使用websocket来进行前后交互的时候,那么它俩有什么区别呢? http和websocket区别 WebSocket是双向通信协...
    99+
    2023-09-12
    java websocket 开发语言 云原生 spring boot
  • 如何操作云服务器手机端
    如果您是使用云服务器进行移动端的云存储,那么您可以使用以下方法操作手机端: 下载并安装手机操作系统。在您的智能手机上安装相应的操作系统以及适配的云服务器软件,可以在各个应用市场或者应用商店中搜索“云服务器”并下载安装。 登录服务器账号。...
    99+
    2023-10-27
    操作 服务器 手机
  • 自己动手写一个能操作redis的客户端
    作者:孤独烟 来源:微信订阅号(程序员孤独烟)原文链接:https://mp.weixin.qq.com/s/IBynkex-FHhvJ3tmizvJhA 引言redis大家在项目中经常会使用到。官网也提供了多语言的客户端供大家操作redi...
    99+
    2023-06-05
  • 云服务器如何防止ddos攻击手机端端口
    攻击者可以通过使用DDoS(分布式拒绝服务)攻击、缓冲区溢出攻击、DNS劫持等方式来攻击云服务器。这些攻击会导致云服务器资源被耗尽,无法提供足够的服务。为了防止DDoS攻击,我们可以采取以下措施: 使用高性能的云服务器 高性能的云服务...
    99+
    2023-10-28
    端端 如何防止 服务器
  • javascript如何写后端
    JavaScript在Web开发中起到的作用越来越重要,不仅仅是在前端开发中,甚至在后端开发中也有广泛的应用。本文将介绍如何使用JavaScript作为后端编程语言。首先,我们需要了解JavaScript在后端编程中的优点。JavaScri...
    99+
    2023-05-22
  • redis如何读写分离
    redis 通过主从复制和客户端配置实现读写分离。优点包括提高读吞吐量、保证写入一致性和提高可用性。需要注意数据一致性、配置复杂性和适用于高读写负载场景。 Redis 如何实现读写分离...
    99+
    2024-04-19
    redis
  • 手机如何登陆阿里云服务器端
    如果您使用的是阿里云提供的服务器,以下是在手机上登录阿里云服务器端的步骤: 打开 Android 手机 应用商店,在其中搜索“阿里云服务器”并下载安装阿里云应用; 打开 Chrome 浏览器,在页面顶部导航栏中找到并进入“开发者工具”;...
    99+
    2023-10-26
    阿里 服务器端 手机
  • 如何用云服务器玩游戏手机端
    用云服务器玩游戏手机端可以节省大量的带宽和存储空间,因为它们使用的是服务器提供的云存储服务。以下是一些步骤,您可以在游戏平台使用云服务器玩游戏。 选择一个合适的云服务器品牌和配置:您可以选择云服务器提供商的品牌和配置,也可以根据自己的需...
    99+
    2023-10-26
    玩游戏 如何用 服务器
  • 手机如何登录阿里云服务器端
    如果您使用的是阿里云手机,以下是登录阿里云服务器端的方法: 点击手机桌面上的“设置”图标。 进入设置页面后,点击“账户与安全”选项。 在“账户与安全”页面中,点击“登录”选项。 在弹出的登录对话框中,输入您的账号和密码,然后点击“登录”...
    99+
    2023-10-27
    阿里 服务器端 手机
  • 云服务器如何重置密码手机端
    首先,让我们来了解一下云服务器的基本知识。云服务器是一种基于互联网的服务器,它通过网络连接到各个设备上,以便用户可以访问和使用它们。在云服务器上,用户可以通过Web浏览器、移动设备或其他应用程序访问它们。云服务器可以通过控制面板或管理控制台...
    99+
    2023-10-28
    密码 服务器 手机
  • 手机端阿里云如何打开服务器
    本文主要介绍如何在手机端使用阿里云打开服务器。首先,需要了解阿里云服务器的基本概念和操作方法,然后在手机上安装阿里云手机客户端,最后按照提示操作,即可在手机端打开阿里云服务器。 阿里云手机客户端是阿里云提供的一款用于管理阿里云服务器的手机应...
    99+
    2023-10-30
    阿里 服务器 手机
  • java如何读取服务器端文件
    要读取服务器端的文件,可以使用Java中的java.net包中的类来建立与服务器的连接,并通过输入流来读取文件内容。以下是一个简单的...
    99+
    2024-04-09
    java 服务器
  • Java Socket服务端具体命令怎么编写
    Java Socket服务端具体命令怎么编写,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。Java Socket服务端一直在不断发展,我们在使用的时候需要不断的进行客户端的维护...
    99+
    2023-06-17
  • 如何关闭云服务器功能提醒服务手机端
    停止云服务器功能 首先,停止云服务器功能可以帮助用户有效地控制资源的使用。在云服务器上运行的应用程序需要一定的存储空间和带宽资源,如果这些资源不能被合理地利用,就会浪费企业的资源。因此,用户需要关闭云服务器功能,以释放这些资源。 控...
    99+
    2023-10-28
    功能 服务器 手机
  • redis读写锁如何解决
    redis 不支持原生的读写锁机制。解决方案包括:第三方工具:redlock 或 rwlock;自定义解决方案:基于令牌机制:使用 read_lock 和 write_lock 键;基于...
    99+
    2024-04-20
    redis
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作