My-Redis

Redis是什么

Redis是一个开源的底层使用C语言编写的key-value内存数据库。可用于缓存数据、事件发布订阅、高速队列等场景,而且支持丰富的数据类型:string(字符串)、hash(哈希)、list(列表)、set(无序集合)、zset(有序集合)。

使用场景

随着数据量的增长,MySQL已经满足不了大型互联网类应用的需求。因此,Redis基于内存存储数据,在某些场景下,就会大大提高效率。

  • 缓存:对于热点数据,缓存以后可能读取数十万次,因此对于热点数据,不但缓存的价值非常大,而且当总数据量比较大的时候直接从数据库中查询会比较影响性能。例如:对经常需要查询且变动不是很频繁的数据,可以考虑基于Redis实现缓存。
  • 会话缓存:Redis还可以进行会话缓存。例如:将web session存放在Redis中。
  • 计数器:因为Redis具有原子性,所以在某些方面可以避免并发问题,比如:统计点击率、点赞率、收藏率等。
  • 消息队列:Redis能作为一个很好的消息队列来使用,依赖List类型利用LPUSH命令将数据添加到链表头部,通过BRPOP命令将元素从链表尾部取出。
  • 社交列表:社交属性相关的列表信息,例如,用户点赞列表、用户分享列表、用户收藏列表、用户关注列表、用户粉丝列表等,使用Hash类型数据结构是个不错的选择。
  • 最新动态:按照时间顺序排列的最新动态,也是一个很好的应用,可以使用Sorted Set类型的分数权重存储时间戳进行排序。
Redis 和 Memcached

说到Redis就会联想到Memcached。Redis与Memcached相比:
① 不仅支持简单的key-value数据类型,同时还提供list、set、zset、hash等数据结构的存储;
② Redis支持数据的备份,即master-slave模式的数据备份;
③ Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用等等。

网络I/O模型:

  • Memcached是多线程非阻塞I/O复用的网络模型,引入了锁的问题,带来了性能损耗。
  • Redis是单线程的I/O复用模型,对于单存只有I/O操作来说,单线程可以将速度优势发挥到最大,但是Redis也提供了一些简单的计算功能,比如排序、聚合等,对于这些操作,单线程模型施加会严重影响整体吞吐量,CPU计算过程中,整个I/O调度都是被阻塞的。

支持的数据类型:

  • Memcached使用key-value形式存储和访问数据,在内存中维护一张巨大的HashTable,使得对数据查询的时间复杂度降低到O(1),保证了对数据的高性能访问。
  • Redis除了支持简单的key-value数据类型,同时还提供list、set、zset、hash等数据结构的存储,补偿了Memcached中的不足。

数据存储及持久化:

  • Memcached不支持内存数据的持久化操作,所有的数据都以in-memory的形式存储,再次重启的时候数据就没有了。
  • Redis支持持久化操作。Redis提供了两种不同的持久化方法来将数据存储到硬盘里面,一种是快照,它可以将存在于某一时刻的所有数据都写入硬盘里面;另一种方法叫只追加文件,它会在执行写命令时,将被执行的写命令复制到硬盘里面。

数据一致性问题:

  • Memcached提供了CAS命令,可以保证多个并发访问操作同一份数据的一致性问题。
  • Redis没有提供CAS命令,但是却提供了事务的功能,可以保证一串命令的原子性,中间不会被任何操作打断。
Redis持久化策略

Reids 是一个 key-value 存储系统,为了保证效率,缓存在内存中,但是 Redis 会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件中,以保证数据的持久化。所以 Redis 是一个支持持久化的内存数据库,可以将内存中的数据同步到磁盘保证持久化。

  • rdb:快照形式,直接把内存中的数据保存到一个dump文件中,定时保存
  • aof:把所有的对 redis 的服务器进行修改的命令都存到一个文件里
rdb:

默认情况下,是快照 rdb 的持久化方式,将内存中的数据以快照的方式写入二进制文件中,默认的文件名是dump.rdb

redis.conf配置:
save 900 1 
save 300 10
save 60 10000

默认是如上配置:900秒之内,如果超过1个key被修改,则发起快照保存;
300秒内,如果超过10个key被修改,则发起快照保存
1分钟之内,如果1万个key被修改,则发起快照保存

这种方式不能完全保证数据持久化,因为是定时保存,所以当redis服务down掉,就会丢失一部分数据,而且数据量大、写操作多的情况下,会引起大量的磁盘IO操作,会影响性能。

AOF:

使用 aof 做持久化,每一个写命令都通过 write 函数追加到 appendonly.aof 中。

配置方式:启动aof持久化的方式 
appendonly yes  
Redis数据类型

String(字符串)

String是Redis的最基本数据结构,以一个键和一个值存储在Redis内部,类似java的Map结构,可以通过键去找值。

Hash(哈希)

Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象,类似Java里面的Map<String, Object>。

List(列表)

根据插入顺序排序的字符串元素的集合,底层实现是链表。

Set(集合)

Redis的Set是string类型的无序集合,它是通过HashTable实现的。

zset(sorted set:有序集合)

Redis zset和set一样也是string类型元素的集合,且不允许重复。但每个字符串元素与浮点数值相关联,称为分数,元素总是按其分数排序,可以检索一系列元素。

Redis协议规范

Redis客户端使用名为RESP(REdis序列化协议)的协议与Redis服务器通信。虽然该协议是专为Redis设计的,但它可以用于其他客户端 - 服务器软件项目。

RESP可以序列化不同的数据类型,如整数,字符串,数组,还有一种特定的错误类型。请求从客户端发送到Redis服务器,作为表示要执行的命令的参数的字符串数组,Redis使用特定于命令的数据类型进行回复。

注意:此处概述的协议仅用于客户端 - 服务器通信。Redis Cluster使用不同的二进制协议,以便在节点之间交换消息。

网络层:客户端连接到Redis服务器,创建到端口6379的TCP连接。

请求 - 响应模型:Redis接受由不同参数组成的命令。收到命令后,将对其进行协议解析,并将回复发送回客户端。

RESP协议说明

RESP协议是在Redis 1.2中引入的,但它成为了与Redis 2.0中的Redis服务器通信的标准方式。这是您应该在Redis客户端中实现的协议。

RESP实际上是一个支持以下数据类型的序列化协议:Simple Strings、Errors、Integers、Bulk Strings、Arrays。

RESP在Redis中用作请求 - 响应协议的方式如下:

客户端将命令作为Bulk Strings的RESP数组发送到Redis服务器,服务器根据命令实现回复一种RESP类型。在RESP中,某些数据的类型取决于第一个字节:

  • 对于Simple Strings,回复的第一个字节是“+”
  • 对于Errors,回复的第一个字节是“ - ”
  • 对于Integers,回复的第一个字节是“:”
  • 对于Bulk Strings,回复的第一个字节是“$”
  • 对于Arrays,回复的第一个字节是“*”
    此外,RESP能够使用指定的Bulk Strings或Array的特殊变体来表示Null值(如:"$-1\r\n""*-1\r\n" 都表示null)。在RESP中,协议的不同部分始终以“\ r \ n”(CRLF)结束。

项目My-Redis设计
项目描述

该项目实现了一个类似 Redis 的小型服务器端。客户端向服务器发送命令,服务器端利用线程池对用户输入做协议解析,不同的命令分发到不同的命令对象中去,接着会对数据库中的数据做处理,并将结果返回给客户端。

该项目并没有对 Redis 的所有命令进行实现,只是实现了其中关于 list 和 hash 的那一部分的 4 个命令,即lpushlrangehset以及hget

项目设计图

在这里插入图片描述

项目源码

https://github.com/jihaojiemo/redis-like

项目中遇到的问题

如何根据二进制字节流解析出命令名称???
项目中实现了一个 Protocol 类,专门用于协议解析,将二进制流转为Java对象。

如何根据命令名称获取到命令所对应的对象???
① 根据命令名称找到对应的类名称,这里采用了约定俗成的办法,把类名称和命令名称设置成一样的。
② 根据类名称获取指定的对象,很容易想到通过反射。具体做法是每次命令创建一个新的对象,相同的命令共用同一个对象(通过单例模式实现)。

项目测试

功能测试:
正常功能:测一次,测多次
非正常功能:边界,特殊字符、特殊长度、大小写
单元测试(覆盖率):对某一个方法做测试(processInteger)–白盒测试(写代码)JUit
代码覆盖率、分支覆盖率
性能测试:指标 redis-benchmark/jedis
响应时间
并发性能:每秒支持的并发数
压力测试:有压力的情况下测功能和性能

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值