这是一个用Netty实现的Redis(服务器版本)
github地址:https://github.com/pyb1993/JavaRedis
目的有三:
- 深入理解redis,将redis上的各种功能慢慢迁移到java上来
用C语言来实现太麻烦了,而且一般工作中用不到C,加上我前两个项目(编译器和http服务器)都是用c写的,正好练习一下Java
降低开发难度,对于一些功能可以更轻松的实现
未来可以用JNI将重要数据结构封装起来,提高性能(另开一个branch) - 理解现代服务器的网络/线程模型
最近刚刚学习了Netty,顺便熟悉netty的使用 - 可以用来学习分布式,实现简单的主从,集群功能
学习分布式不可能只动眼不动手,所以以后可以这个项目为出发点开始魔改
Version-1架构
因为使用了Netty,所以不需要过于操心网络,针对redis本身的特点(来往的数据量比较小,全是纯内存操作,其实cpu开销也不是很大),所以单次操作非常的快,这种情况下,cpu并不是瓶颈,往往网络先达到瓶颈(这里不是指网卡流量跑满,而是说处理各种链接的开销)
所以采取单线程(多线程带来的线程同步的开销相当大,暂时没有必要)
也就是 网络 + 业务 都在一个线程里面(一开始也尝试使用额外的线程池来执行,后面发现没有必要)
Handler
用一个Map维护命令和Handler之间的关系,来一个命令就去查找对应的Handler,然后调用对应的handler
编码/解码:
先不考虑性能
直接使用阿里的FastJson,用来序列化参数(command 对应的类型都利用一个hashMap提前注册好)
协议格式 :
每个单元 长度 + bytes
一共三个单元:
requestId(用来校验)
command(命令类型)
content(结果,也是FastJson序列化的字节)
数据库部分:
在RedisDb.java文件里面,核心是一个
HashMap<String,RedisObject>
RedisObject定义如下:
class RedisObject{
int type;
Object data;
.....
}
实现了HyperLogLog数据结构:
基本原理:
- 令K 为n次投掷「硬币」面最大的投掷次数
- P(A) = 所有投掷次数 P(Xi<=K)=(1−(1/2)k