学习记录篇章之 Redis
目录
前言
Redis,一款用C语言编写的基于内存的NoSQL。在数据量日益增加的今天,Redis等缓存中间件的存在能够很好的帮我们后端数据库的压力。因为如果我们每一次的请求都要流入到数据库中去执行,那么即使性能再优越,效率再高的数据库也无法承担。所以我们可以利用缓存,简单地说就是把一些需要频繁查询的,不经常修改的数据,或者可以把一些频繁查询和修改,但是不需要立刻就存入到数据库中的数据放到缓存中进行操作。
一、Redis的常用数据结构以及使用场景
既然说Redis是一种NoSQL,那作为数据库来存储数据,他也拥有自己的数据结构,下面展示Redis部分主要的数据结构。
1.String
String的简单使用
127.0.0.1:6379> set key value #设置 key-value 类型的值
OK
127.0.0.1:6379> get key # 根据 key 获得对应的 value
"value"
127.0.0.1:6379> exists key # 判断某个 key 是否存在
(integer) 1
127.0.0.1:6379> strlen key # 返回 key 所储存的字符串值的⻓度。
(integer) 5
127.0.0.1:6379> del key # 删除某个 key 对应的值
(integer) 1
127.0.0.1:6379> get key
(nil)
127.0.0.1:6379> mset key1 value1 key2 value2 # 批量设置 key-value 类型的值
OK
127.0.0.1:6379> mget key1 key2 # 批量获取多个 key 对应的 value
1) "value1"
2) "value2"
127.0.0.1:6379> set number 1
OK
127.0.0.1:6379> incr number # 将 key 中储存的数字值增⼀
(integer) 2
127.0.0.1:6379> get number
"2"
127.0.0.1:6379> decr number # 将 key 中储存的数字值减⼀
(integer) 1
127.0.0.1:6379> get number
"1"
127.0.0.1:6379> expire key 60 # 数据在 60s 后过期
(integer) 1
127.0.0.1:6379> setex key 60 value # 数据在 60s 后过期 (setex:[set] + [ex]pire)
OK
127.0.0.1:6379> ttl key # 查看数据还有多久过期
(integer) 56
2.list
list的简单使用
127.0.0.1:6379> rpush myList value1 # 向 list 的头部(右边)添加元素
(integer) 1
127.0.0.1:6379> rpush myList value2 value3 # 向list的头部(最右边)添加多个元素
(integer) 3
127.0.0.1:6379> lpop myList # 将 list的尾部(最左边)元素取出
"value1"
127.0.0.1:6379> lrange myList 0 1 # 查看对应下标的list列表, 0 为 start,1为 end
1) "value2"
2) "value3"
127.0.0.1:6379> lrange myList 0 -1 # 查看列表中的所有元素,-1表示倒数第⼀
1) "value2"
2) "value3"
127.0.0.1:6379> rpush myList2 value1 value2 value3
(integer) 3
127.0.0.1:6379> rpop myList2 # 将 list的头部(最右边)元素取出
"value3"
127.0.0.1:6379> rpush myList value1 value2 value3
(integer) 3
127.0.0.1:6379> lrange myList 0 1 # 查看对应下标的list列表, 0 为 start,1为 end
1) "value1"
2) "value2"
127.0.0.1:6379> lrange myList 0 -1 # 查看列表中的所有元素,-1表示倒数第⼀
1) "value1"
2) "value2"
3) "value3"
#通过 llen 查看链表⻓度:
127.0.0.1:6379> llen myList
(integer) 3
3.Hash
Rdis中的Hash跟JDK1.8前里面的HashMap很像,内部实现也差不多(数组 + 链表)。
Hash的简单使用
127.0.0.1:6379> hset userInfoKey name "xiaoming" description "dev" age "24"
OK
127.0.0.1:6379> hexists userInfoKey name # 查看 key 对应的 value中指定的字段是否存
在。
(integer) 1
127.0.0.1:6379> hget userInfoKey name # 获取存储在哈希表中指定字段的值。
"guide"
127.0.0.1:6379> hget userInfoKey age
"24"
127.0.0.1:6379> hgetall userInfoKey # 获取在哈希表中指定 key 的所有字段和值
"name"
2) "xiaoming"
3) "description"
4) "dev"
5) "age"
6) "24"
127.0.0.1:6379> hkeys userInfoKey # 获取 key 列表
1) "name"
2) "description"
3) "age"
127.0.0.1:6379> hvals userInfoKey # 获取 value 列表
1) "guide"
2) "dev"
3) "24"
127.0.0.1:6379> hset userInfoKey name "honghong" # 修改某个字段对应的值
127.0.0.1:6379> hget userInfoKey name
"honghong"
4.zset
127.0.0.1:6379> zadd myZset 3.0 value1 # 添加元素到 sorted set 中 3.0 为权重
(integer) 1
127.0.0.1:6379> zadd myZset 2.0 value2 1.0 value3 # ⼀次添加多个元素
(integer) 2
127.0.0.1:6379> zcard myZset # 查看 sorted set 中的元素数量
(integer) 3
127.0.0.1:6379> zscore myZset value1 # 查看某个 value 的权重
"3"
127.0.0.1:6379> zrange myZset 0 -1 # 顺序输出某个范围区间的元素,0 -1 表示输出所有元
素1) "value3"
2) "value2"
3) "value1"
127.0.0.1:6379> zrange myZset 0 1 # 顺序输出某个范围区间的元素,0 为 start 1 为
stop
1) "value3"
2) "value2"
127.0.0.1:6379> zrevrange myZset 0 1 # 逆序输出某个范围区间的元素,0 为 start 1
为 stop
1) "value1"
2) "value2"
二、Redis的单线程模型和IO多路复用
Redis 基于 Reactor 模式开发了⾃⼰的⽹络事件处理器:这个处理器被称为⽂件事件处理器( file event handler )。⽂件事件处理器使⽤ I/O 多路复⽤( multiplexing )程序来同时监听多个套接字,并根据 套接字⽬前执⾏的任务来为套接字关联不同的事件处理器。当被监听的套接字准备好执⾏连接应答( accept )、读取( read )、写⼊( write )、关 闭( close )等操作时,与操作相对应的⽂件事件就会产⽣,这时⽂件事件处理器就会调⽤套接字之前关联好的事件处理器来处理这些事件。虽然⽂件事件处理器以单线程⽅式运⾏,但通过使⽤ I/O 多路复⽤程序来监听多个套接字 ,⽂件事件处理器既实现了⾼性能的⽹络通信模型,⼜可以很好地与 Redis 服务器中其他同样以单线程⽅式运⾏的模块进⾏对接,这保持了 Redis 内部单线程设计的简单性。
那么,我们从中得知,文件事件处理器可以分为以下四个部分
Rdis中为什么不使用多线程
对于这个问题,首先这个描述是不准确的,实际上Redis 4.0之后就引入了多线程,主要负责处理一些大键值对数据的删除等操作,大部分对于数据的操作还是单线程的。
那么Redis为什么不使用多线程去操作数据呢。
首先,Redis是基于内存操作的。所以Redis的性能几乎不受CPU的影响,主要与内存的大小以及网络传输方面的因素有关,可以说(多线程是可以有的,但是没有必要)
另外就是,多线程会带来死锁,数据不一致等各方面的问题,如果单线程既能保证效率,又不会带来潜在的危害,那还要什么多线程自行车呀。
这里有一个Redis 6.0的新特性,Redis 6.0引入了多线程操作,只不过不是基于数据读写的,而是在网络层的IO读写引入了多线程,提高了网络数据读写的效率(有兴趣的朋友们可以自行了解)
Redis的缓存过期策略
前面我们已经提到过了,Redis是拥有缓存过期特性的,也就是我们可以给Redis中的数据设置一个过期时间,时间到了我们就无法再使用这个数据了,必须要重新设置。
因为Redis是基于内存的,内存资源总是有限且宝贵的嘛,设置过期时间能很好的保证我们内存容量的健康,同时也可以在某些业务中给我们提供帮助(例如用户Token过期,登录验证码,二维码过期等等)。
过期键的删除策略
Redis中的过期键删除策略主要有以下两种,分别是惰性删除和定期删除。
Redis内存淘汰机制
总结
本篇文章就到这里啦,这篇文章首先认识了一下Redis的概念以及基本数据的使用方法。最后还了解了一下Redis的过期策略和内存淘汰策略。由于篇幅原因,Redis的持久化和使用场景我就下一篇再给大家展示咯。