Redis(一):开篇

1、什么是Redis

Redis 是一种基于键值对(key-value)的 NoSQL 数据库,它的全称是(Remote Dictionary Service)远程字典服务。

Redis 中的值支持 字符串(string)、哈希(hash)、列表(list)、集合(set)、有序集合(zset)、位图(Bitmaps)、HyperLogLog、GEO(地理信息定位)等多种数据结构,因此 Redis 可以满足很多应用场景。

Redis 可以将所有数据存放在内存中,因此它的读写性能非常惊人。不仅如此,Redis 还可以将内存的数据利用快照和日志的形式保存在硬盘上,这样在服务器发生故障时,只要硬盘可以使用,那么其存储的数据就不会丢失。除了以上功能,Redis 还提供了键过期、发布订阅、事务、Lua 脚本等功能。

从 Redis 的官方统计来看,国内外很多大型互联网公司都在使用Redis,如国外的 Twitter、Stack Overflow、GitHub 等;国内的 新浪微博、阿里巴巴、腾讯、百度、搜狐、优酷土豆、美团、小米、唯品会等公司。因此,对 Redis 的了解与应用已经成为当下开发者必备的技能。

2、Redis 可以用来做什么

Redis的业务应用范围非常广泛,以下介绍几种常用的场景

2.1、缓存

Redis 提供了键值过期特性,同时也提供了灵活控制最大内存合内存溢出的淘汰策略。因此合理的使用Redis 缓存数据不仅可以加快数据的访问速度,而且可以有效的降低后端的压力。

2.2、排行榜

对数据进行排行的需求几乎存在与所有的系统或网站,例如:按照热度排行,按照时间排行,按照各种复杂维度计算出的排行。Redis 提供了列表和有序集合数据结构,合理的使用这些数据结构可以很轻松的实现各种维度的排行。

2.3、计数器

Redis 天然支持计数功能,而且计数的性能也非常好,因此经常用于对 视频播放计数、网页浏览计数、或用来做分布式自增ID等。

2.4、社交网络

点赞、踩、粉丝、共同好友或喜好、推送、下拉刷新等都是社交网站必备的功能,由于社交网站访问量通常比较大,而且传统的关系听数据库不太适合保存这种类型的数据,Redis 提供的数据结构可以比较轻松的实现这些功能。

2.5、消息队列

Redis 提供了发布订阅和阻塞队列的功能,虽然与专业的消息队列相比还不够强大,但是对于一般的消息队列功能基本都可以满足。

3、常用全局命令

Redis 的命令有上百个,如果靠死记硬背是很困难的,但是如果理解了 Redis 的一些机制,便会发现这些命令有很强的规律性和通用性。

另外 Redis 不是万能的,有些数据结构和命令必须在特定场景下使用,如果使用不当可能对 Redis 服务或应用本身造成不可知的后果。

3.1、查看所有键

keys *

该命令会将所有键输出

127.0.0.1:6379> keys *
1) "java"
2) "hello"

keys 命令会遍历所有键,所以它的时间复杂度是 O(n),如果 Redis 中有大量键时,不建议使用该命令。

3.2、键总数

dbsize

dbsize 命令会返回当前数据库中键的总数

127.0.0.1:6379> dbsize
(integer) 2

dbsize 命令在计算键总数时不会遍历所有键,而是直接获取 Redis 内置的键总数变量,所以该命令的时间复杂度为 O(1).

3.3、检查键是否存在

exists key

如果键存在返回 1,否则返回 0

127.0.0.1:6379> exists hello
(integer) 1
127.0.0.1:6379> exists hello1
(integer) 0

3.4、删除键

del 是一个通用命令,无论值是什么数据结构类型,del 命令都可以将其删除

del key [key ...]

返回结果是成功删除键的个数,如果删除一个不存在的键,就会返回 0

127.0.0.1:6379> del hello
(integer) 1
127.0.0.1:6379> exists hello
(integer) 0
127.0.0.1:6379> del hello
(integer) 0

3.5、键过期

Redis 支持对键添加过期时间,当超过过期时间后,会自动删除键

expire key seconds

ttl 命令会返回键剩余时间,它有3种返回值:

  • 大于等于0:键剩余的过期时间
  • -1:未设置过期时间
  • -2:键不存在
127.0.0.1:6379> set hello world
OK
127.0.0.1:6379> expire hello 10
(integer) 1
127.0.0.1:6379> ttl hello
(integer) 2
127.0.0.1:6379> ttl hello
(integer) -2
127.0.0.1:6379> exists hello
(integer) 0

3.6、键的数据结构类型

type key

如果键不存在,则返回 none

127.0.0.1:6379> set today monday
OK
127.0.0.1:6379> rpush weeks monday sunday
(integer) 2
127.0.0.1:6379> type today
string
127.0.0.1:6379> type weeks
list
127.0.0.1:6379> type week
none

4、Redis 基本数据结构简介

Redis不是普通的键值存储,它实际上是一个数据结构服务器,支持不同类型的值。 这意味着,在传统的键值存储中,您将字符串键与字符串值相关联,在Redis中,值不仅限于简单的字符串,还可以包含更复杂的数据结构。 以下是Redis支持的所有数据结构的列表,本教程将单独介绍它们:

4.1、String 字符串

string 是redis最基本的类型,一个键最大能存储512MB。string类型是二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象 。

4.2、Hash 哈希

Redis hash 是一个键值(key=>value)对集合。

Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。

Redis Hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象。

每个 hash 可以存储 232 - 1 键值对(40多亿)。

4.3、List 列表

Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素导列表的头部(左边)或者尾部(右边)。
列表最多可存储 232 - 1 元素 (4294967295, 每个列表可存储40多亿)。

4.4、Set 集合

Redis的Set是string类型的无序集合。

集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)

集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。

4.5、ZSet 有序集合

Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。

zset的成员是唯一的,但分数(score)却可以重复。

5、Redis 高级数据结构简介

5.1、Bitmaps 位图

Bitmaps 本身不是一种数据结构,实际上它就是字符串(key 对应的 value 就是上图中最后的一串二进制),但是它可以对字符串的位进行操作。

Bitmaps 单独提供了一套命令,所以在 Redis 中使用 Bitmaps 和使用字符串的方法不太相同。可以把 Bitmaps 想象成一个以 位 为单位的数组,数组的每个单元只能存储 0 和 1,数组的下标在Bitmaps中叫做偏移量。

5.2、HyperLogLogs

Redis 在 2.8.9 版本添加了 HyperLogLog 结构。

Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常大时,计算基数所需的空间总是固定 的、并且是很小的。

在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。

但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。

比如数据集 {1, 3, 5, 7, 5, 7, 8}, 那么这个数据集的基数集为 {1, 3, 5 ,7, 8}, 基数(不重复元素)为5。 基数估计就是在误差可接受的范围内,快速计算基数。

5.3、Streams

Stream是Redis 5.0引入的一种新数据类型,允许消费者等待生产者发送的新数据,还引入了消费者组概念,组之间数据是相同的(前提是设置的偏移量一样),组内的消费者不会拿到相同数据。这种概念和kafka很雷同,kafka消费的时候就是在移动offset,数据依然在。

在某些特定场景可以使用redis的stream代替kafka等消息队列,减少系统复杂性,增强系统的稳定性

官方说他们这个stream是对日志数据结构(log data structure)的高度抽象。stream首先是一个append only日志数据结构,但实现更加的复杂,要比一般的日志文件更强大。

5.4、GEO

Redis 的 GEO 是 3.2 版本的新特性。这个功能可以将用户给定的地理位置信息储存起来, 并对这些信息进行操作。比如:获取某个地理位置的坐标、获取两个地理位置的距离、根据给定地理位置坐标获取指定范围内的地理位置集合等等。

6、Redis 数据结构和内部编码

type 命令返回的是当前键的数据结构类型,分别是:string(字符串)、hash(哈希)、 list(列表)、set(集合)、zset(有序集合),这些是 Redis 对外的数据结构。

实际上每种数据结构都有自己的底层内部编码实现,而且是多种实现,这样 Redis 就会在合适的场景使用合适的内部编码。

Redis 这样设计有两个好处:

第一,可以改进内部编码,而对外的数据结构和命令不受影响,比如 Redis 3.2 提供了 quicklist ,结合了 ziplist 和 linkedlist 的优势,为列表类型提供了一种更为优秀的内部编码实现,而对外来说是无感知不受影响的。

第二,多种内部编码实现可以在不同场景下发挥各自的优势,例如 ziplist 比较节省内存,但是在元素比较多的情况下,性能会有所下降,这时 Redis 会根据配置项将列表类型的内部编码转换为 linedlist.

在这里插入图片描述

7、Redis 单线程为何性能如此高

1、Redis 将所有数据放在内存中,实现纯内存访问,内存的响应时长大约为100纳秒,这也是 Redis 能达到每秒万级别访问的重点所在。

2、Redis 使用 epoll 作为 I/O 多路复用计数的实现,再配合 Redis 自身的事件处理模型将 epoll 中的连接、读写、关闭都转换为事件,避免了在网络 I/O 上浪费太多的时间。

3、单线程避免了线程切换和竞态产生的消耗。

8、Redis 5.x 新特性

1、新的流数据类型(Stream data type) https://redis.io/topics/streams-intro

2、新的 Redis 模块 API:定时器、集群和字典 API(Timers, Cluster and Dictionary APIs)

3、RDB 现在可存储 LFU 和 LRU 信息

4、redis-cli 中的集群管理器从 Ruby (redis-trib.rb) 移植到了 C 语言代码。执行 redis-cli –cluster help 命令以了解更多信息

5、新的有序集合(sorted set)命令:ZPOPMIN/MAX 和阻塞变体(blocking variants)

6、升级 Active defragmentation 至 v2 版本

7、增强 HyperLogLog 的实现

8、更好的内存统计报告

9、许多包含子命令的命令现在都有一个 HELP 子命令

10、客户端频繁连接和断开连接时,性能表现更好

11、许多错误修复和其他方面的改进

12、升级 Jemalloc 至 5.1 版本

13、引入 CLIENT UNBLOCK 和 CLIENT ID

14、新增 LOLWUT 命令 http://antirez.com/news/123

15、在不存在需要保持向后兼容性的地方,弃用 “slave” 术语

16、网络层中的差异优化

17、Lua 相关的改进:

  • 将 Lua 脚本更好地传播到 replicas / AOF
  • Lua 脚本现在可以超时并在副本中进入 -BUSY 状态

18、引入动态的 HZ(Dynamic HZ) 以平衡空闲 CPU 使用率和响应性

19、对 Redis 核心代码进行了重构并在许多方面进行了改进

参考资料:

Redis 5.0 release notes
Introduction to Redis Streams
《Redis 开发与运维》
《Redis 设计与实现》

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值