写点什么

中小型研发团队架构实践:Redis 快速入门及应用

2017 年 11 月 29 日

Redis 的使用难吗?不难,Redis 用好容易吗?不容易。Redis 的使用虽然不难,但与业务结合的应用场景特别多、特别紧,用好并不容易。我们希望通过一篇文章及 Demo,即可轻松、快速入门并学会应用。

一、Redis 简介

Redis 是一个开源的 Key-Value 存储,但又不仅仅是 Key-Value 存储,用官网上的话来说,Redis 是一个数据结构存储,可用作数据库、缓存和消息中间件。相对于传统的 Key-Value 存储 Memcached 来说,Redis 具有如下特点:

  • 速度快
  • 丰富的数据结构,除 String 之外,还有 List、Hash、Set、Sorted Set
  • 单线程,避免了线程切换和锁的性能消耗
  • 原子操作
  • 可持久化(RDB 与 AOF)
  • 发布 / 订阅
  • 支持 Lua 脚本
  • 分布式锁
  • 事务
  • 主从复制与高可用(Redis Sentinel)
  • 集群(3.0 版本以上)

二、Redis 数据结构

1、String

这是最简单的 Redis 类型。如果只使用这种类型,Redis 就像一个可持久化的 Memcached 服务器。

2、List

Redis 的 List 是基于双向链表实现的,可以支持反向查找和遍历。

常用案例:聊天系统、社交网络中获取用户最新发表的帖子、简单的消息队列、新闻的分页列表、博客的评论系统。

3、Hash

Hash 是一个 String 类型的 field 和 value 之间的映射表,请见下图,类似于.NET 中的 Hashtable 和 Dictionary。主要用来存储对象,可以避免序列化的开销和并发修改控制的问题。

4、Set

Set 也是一个列表,不过它的特殊之处在于它是可以自动排重的:当需要存储一个列表数据,而又不希望出现重复的时候,Set 是一个很好的选择(比如 ID 的集合)。并且 Set 提供了判断某个成员是否在一个 Set 集合内的接口,这也是 List 所没有的。

5、Sorted Set

Sorted Set 和 Set 的使用场景类似,区别是 Sorted Set 会根据提供的 score 参数来进行自动排序。当你需要一个有序的并且不重复的集合列表,那么就可以选择 Sorted Set 数据结构。常用案例:游戏中的排行榜。

三、 Redis 重要特性

以下特性请重点看管道和事务。

1、管道

Redis 管道是指客户端可以将多个命令一次性发送到服务器,然后由服务器一次性返回所有结果。管道技术在批量执行命令的时候可以大大减少网络传输的开销,提高性能。

2、事务

Redis 事务是一组命令的集合。一个事务中的命令要么都执行,要么都不执行。如果命令在运行期间出现错误,不会自动回滚。

管道与事务的区别:管道主要是网络上的优化,客户端缓冲一组命令,一次性发送到服务器端执行,但是并不能保证命令是在同一个事务里面执行;而事务是原子性的,可以确保命令执行的时候不会有来自其他客户端的命令插入到命令序列中。

3、分布式锁

分布式锁是控制分布式系统之间同步访问共享资源的一种方式。在分布式系统中,常常需要协调他们的动作,如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要互斥来防止彼此干扰来保证一致性,在这种情况下,便需要使用到分布式锁。

4、地理信息

从 Redis 3.2 版本开始,新增了地理信息相关的命令,可以将用户给定的地理位置信息(经纬度)存储起来,并对这些信息进行操作。

四、 使用方法

步骤 1、在需要使用 Redis 的项目中引用 FxCommon.dll 和 Redis.dll

步骤 2、在 App.config 或 Web.config 文件中添加如下配置

复制代码
<add key="RedisServerIP" value="redis:uuid845tylabc123@139.198.13.12:4125"/>
<!-- 提供的 Redis 环境是单机版配置。如果 Redis 是主从配置,则还需设置 RedisSlaveServerIP-->
<!--<add key="RedisSlaveServerIP" value="redis:uuid845tylabc123@139.198.13.13:4125"/>-->
<!--Redis 数据库。如果不需要指定 Redis 数据库,就配置默认值 0-->    
<add key="RedisDefaultDb" value="0"/>

步骤 3、使用 PooledRedisClientManager 类创建 Redis 连接池:

复制代码
// 读取 Redis 主机 IP 配置信息
string[] redisMasterHosts = ConfigurationManager.ConnectionStrings["RedisServerIP"].ConnectionString.Split(',');
// 如果 Redis 服务器是主从配置,那么还需要读取 Redis Slave 机的 IP 配置信息
string[] redisSlaveHosts = null;
var slaveConnection = ConfigurationManager.ConnectionStrings["RedisSlaveServerIP"];
if (slaveConnection != null && !string.IsNullOrWhiteSpace(slaveConnection.ConnectionString))
{    
   string redisSlaveHostConfig = slaveConnection.ConnectionString;    
   redisSlaveHosts = redisSlaveHostConfig.Split(',');
}
// 读取 RedisDefaultDb 配置
int defaultDb = 0;
string defaultDbSetting = ConfigurationManager.AppSettings["RedisDefaultDb"];
if (!string.IsNullOrWhiteSpace(defaultDbSetting))
{    
   int.TryParse(defaultDbSetting, out defaultDb);
}
var redisClientManagerConfig = new RedisClientManagerConfig
{    
   MaxReadPoolSize = 50,    
   MaxWritePoolSize = 50,    
   DefaultDb = defaultDb
};
// 创建 Redis 连接池
Manager = new PooledRedisClientManager(redisMasterHosts, redisSlaveHosts, redisClientManagerConfig)
{    
   PoolTimeout = 2000,    
   ConnectTimeout = 500                
};

步骤 4、通过 PooledRedisClientManager 的实例获取 Redis 客户端,然后就可以开始通过 Redis 客户端的 API 进行操作。

五、其它

5.1、 Redis Key 命名规范

Redis Key 命名规范:AppID:KeyName。

可能有很多人习惯用英文状态的点号来作为 AppID 和 KeyName 的分隔符,而笔者建议使用冒号作为 AppID 和 KeyName 的分隔符,其原因是:这么写会使 Redis Key 会以 AppID 作为分类显示在 Redis Desktop Manager 中,方便你能够快速查到要查阅的 Redis Key 对应的 Redis Value 值,请见下图:

但如果使用英文状态的点号来作为分隔符的话,那么在Redis Desktop Manager 中,Redis Key 就不会被分类了,请见下图:

5.2、常见应用问题

  • 缓存穿透处理:什么是缓存穿透?当根据 Redis key 在缓存中查询后,不存在对应 Value,就应该会在后端系统如 DB 中去查找,该 Key 的并发请求量一旦变大,那么就会对 DB 造成很大的压力。解决办法有:a. 前端风险控制,将恶意穿透情况排除在外;b. 对查询结果为空的情况依然进行缓存,但缓存时间会设置得很短,一般是几分钟。
  • 缓存雪崩处理:什么是缓存雪崩?当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,也会给后端系统 (比如 DB) 带来很大压力。解决办法有:后端连接数限制,错误阈值限制,超时处理,缓存失效时间均匀分布,前端永不失效及后端主动更新。
  • 缓存时长:策略定位复杂,需要多维度的计算。
  • 缓存失效:按时失效,事件失效,后端主动更新。
  • 缓存 Key:Hash、规则、前缀 +Hash,异常情况可人工干预。
  • Lua 脚本:服务端批量处理及事务能力,有条件逻辑的可扩展脚本。使用它的好处有:减少网络开销、原子操作、可复用。
  • Limit:可滑动时间窗口,如应用于 Session,Memcached 需每次传 Key 和 Value。

六、Demo 下载及更多资料

本系列文章涉及内容清单如下,其中有感兴趣的,欢迎关注:

作者介绍

张辉清,10 多年的 IT 老兵,先后担任携程架构师、古大集团首席架构、中青易游 CTO 等职务,主导过两家公司的技术架构升级改造工作。现关注架构与工程效率,技术与业务的匹配与融合,技术价值与创新。

杨丽,拥有多年互联网应用系统研发经验,曾就职于古大集团,现任职中青易游的系统架构师,主要负责公司研发中心业务系统的架构设计以及新技术积累和培训。现阶段主要关注开源软件、软件架构、微服务以及大数据。

感谢雨多田光对本文的审校。

2017 年 11 月 29 日 17:079465

评论

发布
暂无评论
发现更多内容

基于环信sdk在uni-app中快速开发多平台社交Demo

DT极客

如何优雅的实现分布式锁

张坚

redis zookeeper 分布式锁

Spring Cloud Kubernetes之实战网关Gateway

Damon

Kubernetes 容器 Spring Cloud 微服务冶理

JVM源码分析之深入分析Object类finalize()方法的实现原理

猿灯塔

JVM

个人技术成长与发展

颇风

后端 技术人

ClickHouse为何如此之快?

nauu

数据库 大数据 OLAP Clickhouse

看完这篇操作系统,和面试官扯皮就没问题了

cxuan

操作系统 计算机基础

spring注入bean的几种策略模式

测试轩

Java Spring Boot 测试驱动开发实战营

严选合伙人(一)

Neco.W

创业 合伙人 初创公司

数据分析的利器-clickhouse概述

流沙

数据库 Clickhouse

太赞了,VSCode 上也能画流程图了!

GitHubDaily

visual-studio GitHub 程序员 vscode 开发者工具

从ClickHouse的名字由来讲起

nauu

数据库 大数据 分布式 OLAP Clickhouse

搜商:高效的使用搜索引擎

石云升

高效搜索 搜索技巧 搜商

【大咖说问大咖】关于开源的那些事 —— PingCAP CTO 黄东旭 Q&A 交流帖

InfoQ写作平台官方

开源 写作平台 大咖说 技术交流 活动专区

提升编程效率:重构

Page

高效工作 敏捷开发 重构 高效

Linux 容器化技术的前世今生(虚拟化、容器化、Docker)

Meandni

Docker 云计算 Linux 容器 虚拟机

何时开始重构?

Page

敏捷开发 重构

真的!只需 “六步” 实现图像特定物体识别!!!

攀鱼飞岩

Python OpenCV 计算机视觉 图像识别 物体检测

练习英语口语的误区

七镜花园-董一凡

学习

如何认识更多的朋友扩展社交朋友圈的质量

吃素的左撇子

人生 人脉

Android | Tangram动态页面之路(一)需求背景

哈利迪

android

Kafka零数据丢失的配置方案

奈学教育

kafka kafka配置 kafka数据

Intellij IDEA2020.x如何安装Lombok插件

龙眼果

开发者工具

游戏夜读 | 预测问题的硬核是?

game1night

MySQL索引知识介绍

Simon

MySQL 索引结构

Serverless: 2020年函数计算的冷启动怎么样了

刘宇

为什么我喜欢的大V拉黑我?

lmymirror

经历 后真相时代 日常思考

工程师、程序员和产品经理

王泰

程序员 产品经理 IT 软件工程师 工程师思维

敏捷团队成员的工作量指标真的那么重要吗?

金生水起

敏捷开发 Scrum精髓 敏捷精髓 Agile

KK日知录20200515

kimmking

原创 | 使用JUnit、AssertJ和Mockito编写单元测试和实践TDD (七)CORRECT边界条件

编程道与术

Java 编程 软件测试 TDD 单元测试

演讲经验交流会|ArchSummit 上海站

演讲经验交流会|ArchSummit 上海站

中小型研发团队架构实践:Redis快速入门及应用-InfoQ