写点什么

中小型研发团队架构实践: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:079390

评论

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

北纬37°的浪漫与理性,穿越千年的信息之变

脑极体

面试必问系列,源码解析多线程绝对不容忽视得问题:线程活性故障

小Q

Java 学习 架构 面试 多线程

阿里P8传授给小老弟的Java面试宝典,竟让让小弟也拿到了P8的offer,傻眼了

Java架构之路

Java 程序员 架构 面试 编程语言

阿里大牛亲自总结整理的一线互联网公司面试真题及面经(阿里、网易、字节)

Java架构之路

Java 程序员 架构 面试 编程语言

架构师训练营第 13 周课后练习

薛凯

炸锅了!国内首本通用源码阅读指定书籍:MyBatis源码详解

周老师

Java 编程 程序员 架构 面经

列举出常见的Java面试题100+,我靠这个在十月拿到了阿里的offer

Java架构之路

Java 程序员 架构 面试 编程语言

工厂模式学习

en

golang 设计模式 工厂模式

2020年11月最新分享,我凭借这份pdf拿下了蚂蚁金服、字节跳动等大厂的offer

Java成神之路

Java 程序员 架构 面试 编程语言

面试阿里被质问:ConcurrentHashMap线程安全吗

Java架构师迁哥

[架构师训练营第 1 期] 第 13 周学习总结

猫切切切切切

极客大学架构师训练营

某程序员刷完这两份pdf轻松拿下了蚂蚁金服、头条、小米等大厂的offer。

Java成神之路

Java 程序员 架构 面试 编程语言

第四周 系统架构 作业 「架构师训练营 3 期」

feiyun123

极客大学架构师训练营

第四周 系统架构 学习总结

feiyun123

极客大学架构师训练营

架构训练营-week13-作业1

于成龙

架构训练营

如何透彻理解 Redis 核心原理?怎样才能形成 Redis 系统观?

Java架构师迁哥

7年开发的老油条,你不跳槽怎么涨薪?看我怎么拿到阿里P7offer的

Java成神之路

Java 程序员 架构 面试 编程语言

架构师训练营第 13 周作业

netspecial

极客大学架构师训练营

智慧平安社区平台建设app,公安大数据分析系统开发

WX13823153201

智慧平安社区平台建设

架构训练营-week13-总结

于成龙

可视化指挥调度平台搭建,应急指挥调度监控中心建设方案

t13823115967

可视化 指挥调度

区块链落地应用开发- 珠宝溯源,不当“冤大头”

13828808769

区块链技术 区块链落地开发 珠宝溯源

Swift函数调用逆向分析

ios swift

泡泡玛特市值千亿背后,我们为什么会为盲盒买单?

脑极体

从月薪3K的Java菜鸟,到年薪80W的Java架构师,靠这份文档,让我学习像打怪升级一样简单!

Java架构之路

Java 程序员 架构 面试 编程语言

智慧城市管理平台,多规合一平台搭建解决方案

t13823115967

智慧城市

mybatis一级缓存是啥?5个面试题回答你

田维常

mybatis

DeFi流动性挖矿系统APP软件开发

开發I852946OIIO

系统开发

字节三面远程,Java+Redis+网络+数据库+算法,轻松反杀面试官?

Java成神之路

Java 程序员 架构 面试 编程语言

天猫Java研发岗面经(技术三面):基础+算法+MySQL+Redis+秒杀架构

Java成神之路

Java 程序员 架构 面试 编程语言

LeetCode题解:18. 四数之和,哈希表,JavaScript,详细注释

Lee Chen

算法 LeetCode 前端进阶训练营

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