文章目录
- 前言
- 一、选型
- 二、协议
- 三、客户端
- 1、常见 java 客户端
- 2、常见可视化工具:
- 四、Redis 生态
- 1、模块
- 2、代理
- 3、其他
前言
Redis(Remote Dictionary Server),即「远程字典服务」是一个使用 ANSI C 编写的、开源的、支持网络的、基于内存的、可选持久化的键值对存储系统。
在 2013 年 5 月之前,Redis 的开发由 VMware 赞助,2013 年 5 月至 2015 年 6 月,由 Pivotal 赞助,从 2015 年 6 月起,Redis 的开发由 Redis Labs 赞助。
根据数据库使用排行网站 db-engines.com 上的排名,Redis 是目前最流行
的键值对存储系统。
Redis 由 Salvatore Sanfilippo 在 2009 年发布初始版本,开源后不断发展壮大,目前的最新版为 Redis 7.0
一、选型
目前业内主要的缓存组件有:redis、memcached,主要特点如下:
用一句话总结:在性能相差不大的情况下,Redis 提供了更丰富的数据类型,同时,对可靠性以及扩展性也提供了较好的支持。
二、协议
全称:Redis Serialization Protocol,即 Redis 序列化协议,有以下三个显著特点:
- 人类易读
- 简单实现
- 快速解析
RESP2 协议如下:
是不是非常简单?
Redis6.0
版本开始,协议进行了升级,即 支持 RESP3
协议,相较于 RESP2 提供了更「语义化」能力,比如支持 double
、boolean
等类型。
值得注意的是,在 Redis6.x 版本中同时支持 RESP2 和 RESP3,但在 Redis7.0
及之后的版本将不再支持 RESP2,届时,所有的客户端将进行全面升级(如果你需要使用7.0及之后的版本)
三、客户端
支持 RESP 协议、封装 Redis 命令的 SDK,其主要作用是帮助我们与服务端进行通信,目前已经提供了非常多的开源客户端实现,支持 C、Java、Python … 等多种语言。
笔者工作中主要用 Java 进行开发,这里主要列举 Java 相关的客户端 SDK。
1、常见 java 客户端
1)目前常见的 Java 客户端工具库有:
- jedis:老牌 java 客户端,redis 命令的 java 版“翻译”
- lettuce:底层依赖 netty 组件进行网络通信,支持异步、响应式编程
- redisson:高级客户端,实现了一些常用的 redis 工具,如 分布式锁、限流器、布隆过滤器等,底层也依赖 netty 组件。
2)Spring 体系:
- spring-data-redis:按 spring 风格,对接口进一步封装、抽象。底层依赖jedis/lettuce/redisson 提供能力,默认使用 lettuce。
- spring-cache:Spring 提供的 cache 抽象层,对应用提供注解支持,底层支持 Caffeine、EhCache、Redis 等多种缓存实现。
例如:当你想用 spring-cache 注解能力并且底层要依赖 redis 时,你可以先添加依 spring-data-redis
包依赖,然后 spring 进行自动扫描就可以了。
3)其他:
- jetCache:阿里提供的缓存解决方案,相当于 SpringCache 提供更有效的注解支持,支持原生TTL、二级缓存、自动刷新等。目前底层实现有 RedisCache、TairCache、CaffeineCache 以及 LinkedHashMapCache。
这么多该如何选择?
工具不在于多,关键看你自身的场景下是否够用,比如你的项目可以只使用 jedis
,当然,后面你可能还想使用「分布式锁」「限流器」等支持,可以再使用 redisson
。(搞懂核心问题,不迷路~
2、常见可视化工具:
Redis Desktop Manager(RDM):一款好用的 Redis 桌面管理工具,支持命令控制台操作,以及常用查询 key、rename、delete 等操作:
RedisInsight:官方提供可视化工具,可用于查询、修改和分析数据。
选择一款用的顺手的可视化工具,提升效率~
四、Redis 生态
1、模块
Module 模块:Redis 提供的可自定义扩展的能力,支持灵活编写适用于自身场景的功能。
目前一些常见开源模块实现:RedisJson、RedisSearch、RedisBloom 等,使用其他和 Redis 命令风格一致,如:
如何实现自定义模块并使用?
- Redis 的模块采用的是动态链接库的方式,可以启动的时候加载,也可以在运行时加载。
- 要实现分离,首先需要的是初始化,以便让框架可以找到对应的方法,这就需要进行注册,Redis 通过 RedisModule_Init 方法进行注册模块,使用 RedisModule_CreateCommand 注册自定义方法。
- Redis 提供了 redismodule.h 头文件,通过实现该头文件相关 API 函数,然后编译为 so 动态库,可以在配置文件中使用 loadmodule 指明,也可以在运行时使用命令动态加载。
最简单的例子:
#include "redismodule.h"
#include <stdlib.h>
int HelloworldRand_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
RedisModule_ReplyWithLongLong(ctx,rand());
return REDISMODULE_OK;
}
int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
if (RedisModule_Init(ctx,"helloworld",1,REDISMODULE_APIVER_1)
== REDISMODULE_ERR) return REDISMODULE_ERR;
if (RedisModule_CreateCommand(ctx,"helloworld.rand",
HelloworldRand_RedisCommand, "fast random",
0, 0, 0) == REDISMODULE_ERR)
return REDISMODULE_ERR;
return REDISMODULE_OK;
}
该案例提供两个方法,其中 HelloworldRand_RedisCommand 是我们自定义的命令,用以输出随机数,实现了 redismodule.h
中的 RedisModule_ReplyWithLongLong 方法。
而 RedisModule_OnLoad 方法则是通过 RedisModule_Init 和 RedisModule_CreateCommand 将我们自定义的命令注册到 Redis。
两种加载方式:
- 配置化:即在 redis.config 文件中配置 loadmodule /path/to/mymodule.so
- 运行时:执行 MODULE LOAD /path/to/mymodule.so
另外我们还可以使用命令查看模块列表:
MODULE LIST
也可以卸载模块:
MODULE UNLOAD mymodule
2、代理
目前代理有两种主要用途:
- 集群能力:需要在 proxy 做路由,因此也需要维护元数据信息
- 客户端能力:将客户端的部分能力移至 proxy,比如哨兵或集群信息变更通知客户端等,proxy 对客户端提供访问 IP,后续 redis 服务任何变更都不需要通知客户端,对客户端十分友好。
1)社区早期集群方案:Codis、Temproxy
特点:redis 服务节点间无交流、代理层做路由、需要单独部署高可用(如哨兵)
2)predixy:支持多种 redis 运行模式,对客户端友好
这种 proxy 便是代理「客户端能力」,将「与 redis 服务交互的部分能力」移到代理层处理。
对客户端来说,直接访问代理层,redis 服务如何变化无需感知,这是目前大多数云服务厂商常用的方式,对客户端十分友好。
3、其他
工具:
- 解析:python 版RDB文件解析工具:Redis-rdb-tools
- 迁移:C 版本的 redis-migrate-tool 迁移工具
- …
可以看到,目前已经提供了多种语言的开源客户端、支持多种系统、同时也支持容器化部署 … ,其生态俨然十分强大了。