您现在的位置是:首页 >其他 >Redis详解网站首页其他

Redis详解

~小安同学 2024-06-13 12:01:02
简介Redis详解

课程目标:

1 Redis 概述
2 、下载与安装
3 、使用 Redis

1. 概述

1.1 互联网架构的演变历程

● 第1阶段

        ○ 数据访问量不大,简单的架构即可搞定!

● 第2阶段

         ○ 数据访问量大,使用缓存技术来缓解数据库的压力。
         ○ 不同的业务访问不同的数据库

● 第3阶段

        ○ 主从读写分离。
        ○ 之前的缓存确实能够缓解数据库的压力,但是写和读都集中在一个数据库上,压力又来了。
        ○ 一个数据库负责写,一个数据库负责读。分工合作。愉快!
        ○ 让master(主数据库)来响应事务性 (增删改) 操作,让 slave (从数据库)来响应非事务性 (查询) 操作,然后再采用主从复制来把 master 上的事务性操作同步到 slave 数据库中
        ○ mysql的master/slave 就是网站的标配!

● 第4阶段 

        ○ mysql的主从复制,读写分离的基础上,mysql 的主库开始出现瓶颈
        ○ 由于MyISAM使用表锁,所以并发性能特别差
        ○ 分库分表开始流行,mysql也提出了表分区,虽然不稳定,但我们看到了希望
        ○ 开始吧,mysql集群

 1.2 Redis入门介绍

● 互联网需求的3高
        ○ 高并发,高可扩,高性能。
● Redis 是一种运行速度很快,并发性能很强,并且运行在内存上的 NoSql not only sql )数据库
● NoSQL数据库 和 传统数据库 相比的优势
         ○ NoSQL数据库无需事先为要存储的数据建立字段,随时可以存储自定义的数据格式。
         ○ 而在关系数据库里,增删字段是一件非常麻烦的事情。如果是非常大数据量的表,增加字段 简直就是一个噩梦。
● Redis的常用使用场景
        ○ 缓存 ,毫无疑问这是 Redis 当今最为人熟知的使用场景。在提升服务器性能方面非常有效;一 些频繁被访问的数据,经常被访问的数据如果放在关系型数据库,每次查询的开销都会很大,而放在redis 中,因为 redis 是放在内存中的可以很高效的访问;
        ○ 排行榜 ,在使用传统的关系型数据库( mysql oracle 等)来做这个事儿,非常的麻烦,而利
Redis SortSet( 有序集合 ) 数据结构能够简单的搞定;
        ○ 计算器/ 限速器 ,利用 Redis 中原子性的自增操作,我们可以统计类似用户点赞数、用户访问
数等,这类操作如果用 MySQL ,频繁的读写会带来相当大的压力;限速器比较典型的使用场景是限制某个用户访问某个API 的频率,常用的有抢购时,防止用户疯狂点击带来不必要的压力;
        ○ 好友关系 ,利用集合的一些命令,比如求交集、并集、差集等。可以方便搞定一些共同好
友、共同爱好之类的功能;
        ○ 简单消息队列 ,除了 Redis 自身的发布 / 订阅模式,我们也可以利用 List 来实现一个队列机制, 比如:到货通知、邮件发送之类的需求,不需要高可靠,但是会带来非常大的DB 压力,完全
可以用 List来完成异步解耦;
        ○ Session共享 ,以 jsp 为例,默认 Session 是保存在服务器的文件中,如果是集群服务,同一个用户过来可能落在不同机器上,这就会导致用户频繁登陆;采用Redis 保存 Session 后,无论
用户落在那台机器上都能够获取到对应的 Session 信息。

1.3 Redis/Memcache/MongoDB对比

都是 nosql 数据库的著名代表

1.3.1 RedisMemcache

● Redis和 Memcache 都是内存数据库。不过 memcache 还可用于缓存其他,例如图片、视频等。
● memcache 数据结构单一 kv redis 更丰富一些,还提供 list set hash 等数据结构的存储,有
效的减少网络 IO 的次数。
● 虚拟内存–Redis 当物理内存用完时,可以将一些很久没用到的 value 交换到磁盘。
存储数据安全 –memcache 挂掉后,数据没了(没有持久化机制); redis 可以定期保存到磁盘(持久化)。
● 灾难恢复–memcache 挂掉后,数据不可恢复 ; redis 数据丢失后可以通过 RBD AOF 恢复。

1.3.2 RedisMongoDB

● redis和 mongodb 并不是竞争关系,更多的是一种 协作共存 的关系。
● mongodb本质上还是硬盘数据库,在复杂查询时仍然会有大量的资源消耗,而且在处理复杂逻辑
时仍然要不可避免地进行多次查询。
● 这时就需要redis Memcache 这样的内存数据库来作为中间层进行缓存和加速。
● 比如在某些复杂页面的场景中,整个页面的内容如果都从mongodb 中查询,可能要几十个查询语
句,耗时很长。如果需求允许,则可以把整个页面的对象缓存至 redis 中,定期更新。这样 mongodb和 redis 就能很好地协作起来。

1.4 分布式数据库CAP原理

● 传统的关系型数据库事务具备ACID
        ○ A:原子性
        ○ C:一致性
        ○ I:独立性
        ○ D:持久性
● 分布式数据库的CAP:
        ○ C(Consistency ):强一致性
                ■  “all nodes see the same data at the same time”,即更新操作成功并返回客户端后,
                   有节点在同一时间的数据完全一致 ,这就是分布式的一致性。一致性的问题在并发系                       统中不可避免,对于客户端来说,一致性指的是并发访问时更新过的数据如何获取的                       问题。从服务端来看,则是更新如何复制分布到整个系统,以保证数据最终一致。
       ○  A(Availability ):高可用性
                ■ 可用性指“Reads and writes always succeed”,即 服务一直可用 ,而且要是正常的响应
                   时间。好的可用性主要是指系统能够很好的为用户服务,不出现用户操作失败或者访                       问超时等用户体验不好的情况。
        ○ P(Partition tolerance ):分区容错性
                ■ 即分布式系统在遇到 某节点或网络分区故障时,仍然能够对外提供满足一致性或可用                     性 的服务
                ■ 分区容错性要求能够使应用虽然是一个分布式系统,而看上去却好像是在一个可以运                     转正常的整体。比如现在的分布式系统中有某一个或者几个机器宕掉了,其他剩下的                       机器还能够正常运转满足系统需求,对于用户而言并没有什么体验上的影响。

1.4.2 CAP理论

● CAP理论提出就是针对分布式数据库环境的,所以, P 这个属性必须容忍它的存在,而且是必须     具备的。
● 因为P 是必须的,那么我们需要选择的就是 A C
● 大家知道,在分布式环境下,为了保证系统可用性,通常都采取了复制的方式,避免一个节点损
   坏,导致系统不可用。那么就出现了每个节点上的数据出现了很多个副本的情况,而数据从一个     节点复制到另外的节点时需要时间和要求网络畅通的,所以,当P 发生时,也就是无法向某个节     点复 制数据时,这时候你有两个选择:
                ○ 选择可用性 A,此时,那个失去联系的节点依然可以向系统提供服务,不过它的数据                       就不能保证是同步的了(失去了C 属性)。
                ○ 选择一致性C,为了保证数据库的一致性,我们必须等待失去联系的节点恢复过来,                       在这个过程中,那个节点是不允许对外提供服务的,这时候系统处于不可用状态( 失去                     了 A 属性 )
● 最常见的例子是读写分离,某个节点负责写入数据,然后将数据同步到其它节点,其它节点提       供读取的服务,当两个节点出现通信问题时,你就面临着选择A (继续提供服务,但是数据不保     证准确),C (用户处于等待状态,一直等到数据同步完成)。

1.4.3 CAP总结

● 分区是常态,不可避免,三者不可共存
可用性和一致性是一对冤家
          ○ 一致性高,可用性低
          ○ 一致性低,可用性高
● 因此,根据 CAP 原理将 NoSQL 数据库分成了满足 CA 原则、满足 CP 原则和满足 AP 原则三 大类:
          ○ CA - 单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大。
          ○ CP - 满足一致性,分区容忍性的系统,通常性能不是特别高。
          ○ AP - 满足可用性,分区容忍性的系统,通常可能对一致性要求低一些。

2. 下载与安装

2.1 下载

● redis: http://www.redis.net.cn/

 ● 图形工具:https://redisdesktop.com/download

2.2 安装 

虽然可以在安装在 windows 操作系统,但是官方不推荐,所以我们一如既往的安装在 linux
        1. 上传 tar.gz 包,并解压
tar -zxvf redis-5.0.4.tar.gz
        2. 安装 gcc (必须有网络)
yum -y install gcc

忘记是否安装过,可以使用 gcc -v 命令查看gcc版本,如果没有安装过,会提示命令不存在

        3. 进入redis 目录,进行编译
make
        4. 编译之后,开始安装
make install

2.3 安装后的操作

2.3.1 后台运行方式

● redis默认不会使用后台运行,如果你需要,修改配置文件 daemonize=yes ,当你后台服务启动的
时候,会写成一个进程文件运行。
vim /opt/redis-5.0.4/redis.conf
daemonize yes
● 以配置文件的方式启动
cd /usr/local/bin
redis-server /opt/redis-5.0.4/redis.conf

2.3.2 关闭数据库

● 单实例关闭
redis-cli shutdown

● 多实例关闭

redis-cli -p 6379 shutdown

2.3.3 常用操作

● 检测6379 端口是否在监听
netstat -lntp | grep 6379
端口为什么是 6379
6379 在是手机按键上 MERZ 对应的号码,
MERZ 取自意大利歌女 Alessia Merz 的名字。
MERZ 长期以来被 antirez redis 作者)及其朋友当作愚蠢的代名词。

● 检测后台进程是否存在 

ps -ef|grep redis

2.3.4 连接redis并测试

redis-cli
ping

2.3.5 HelloWorld

# 保存数据
set k1 china
# 获取数据
get kl

2.3.6 测试性能

● 先 ctrl+c ,退出 redis 客户端
redis-benchmark
● 执行命令后,命令不会自动停止,需要我们手动ctrl+c 停止测试
[root@localhost bin]# redis-benchmark
====== PING_INLINE ======
100000 requests completed in 1.80 seconds # 1.8秒处理了10万个请求,性能要看笔记
本的配置高低
50 parallel clients
3 bytes payload
keep alive: 1
87.69% <= 1 milliseconds
99.15% <= 2 milliseconds
99.65% <= 3 milliseconds
99.86% <= 4 milliseconds
99.92% <= 5 milliseconds
99.94% <= 6 milliseconds
99.97% <= 7 milliseconds
100.00% <= 7 milliseconds
55524.71 requests per second # 每秒处理的请求数量

2.3.7 默认16个数据库

vim /opt/redis-5.0.4/redis.conf

127.0.0.1:6379> get k1 # 查询k1
"china"
127.0.0.1:6379> select 16 # 切换16号数据库
(error) ERR DB index is out of range # 数据库的下标超出了范围
127.0.0.1:6379> select 15 # 切换15号数据库
OK
127.0.0.1:6379[15]> get k1 # 查询k1
(nil)
127.0.0.1:6379[15]> select 0 # 切换0号数据库
OK
127.0.0.1:6379> get k1 # 查询k1
"china

2.3.8 数据库键的数量

dbsize
redis linux 支持命令补全( tab

2.3.9 清空数据库

● 清空当前库
flushdb

● 清空所有(16个)库,慎用!!

flushall

2.3.10 模糊查询(key

模糊查询 keys 命令,有三个通配符:
        ● *:通配任意多个字符
# 查询所有的键
keys *
# 模糊查询k开头,后面随便多少个字符
keys k*
# 模糊查询e为最后一位,前面随便多少个字符
keys *e
# 双 * 模式,匹配任意多个字符:查询包含k的键
keys *k*
         ● ?:通配单个字符
# 模糊查询k字头,并且匹配一个字符
keys k?
# 你只记得第一个字母是k,他的长度是3
keys k??

        ● []:通配括号内的某一个字符

# 记得其他字母,就第二个字母可能是a或e
keys r[ae]dis

2.3.11 键(key

        ● exists key:判断某个key是否存在
127.0.0.1:6379> exists k1
(integer) 1 # 存在
127.0.0.1:6379> exists y1
(integer) 0 # 不存在
        ● move key db:移动(剪切,粘贴)键到几号库
127.0.0.1:6379> move x1 8 # 将x1移动到8号库
(integer) 1 # 移动成功
127.0.0.1:6379> exists x1 # 查看当前库中是否存在x1
(integer) 0 # 不存在(因为已经移走了)
127.0.0.1:6379> select 8 # 切换8号库
OK
127.0.0.1:6379[8]> keys * # 查看当前库中的所有键
1) "x1"
        ● ttl key:查看键还有多久过期(-1 永不过期, -2 已过期)
        ● time to live 还能活多久
127.0.0.1:6379[8]> ttl x1
(integer) -1 # 永不过期
        ● expire key 秒:为键设置过期时间(生命倒计时)
127.0.0.1:6379[8]> set k1 v1 # 保存k1
OK
127.0.0.1:6379[8]> ttl k1 # 查看k1的过期时间
(integer) -1 # 永不过期
127.0.0.1:6379[8]> expire k1 10 # 设置k1的过期时间为10秒(10秒后自动销毁)
(integer) 1 # 设置成功
127.0.0.1:6379[8]> get k1 # 获取k1
"v1"
127.0.0.1:6379[8]> ttl k1 # 查看k1的过期时间
(integer) 2 # 还有2秒过期
127.0.0.1:6379[8]> get k1
(nil)
127.0.0.1:6379[8]> keys * # 从内存中销毁了
(empty list or set)
        ● type key:查看键的数据类型
127.0.0.1:6379[8]> type k1
string # k1的数据类型是会string字符串

3. 使用Redis

3.1 五大数据类型

        ● 操作文档: http://redisdoc.com/

3.1.1 字符串String

        ● set/get/del/append/strlen
127.0.0.1:6379> set k1 v1 # 保存数据
OK
127.0.0.1:6379> set k2 v2 # 保存数据
OK
127.0.0.1:6379> keys *
1) "k1"
2) "k2"
127.0.0.1:6379> del k2 # 删除数据k2
(integer) 1
127.0.0.1:6379> keys *
1) "k1"
127.0.0.1:6379> get k1 # 获取数据k1
"v1"
127.0.0.1:6379> append k1 abc # 往k1的值追加数据abc
(integer) 5 # 返回值的长度(字符数量)
127.0.0.1:6379> get k1
"v1abc"
127.0.0.1:6379> strlen k1 # 返回k1值的长度(字符数量)
(integer) 5
        ● incr/decr/incrby/decrby:加减操作,操作的必须是数字类型
                ○ incr:意思是increment,增加
                ○ decr:意思是decrement,减少
127.0.0.1:6379> set k1 1 # 初始化k1的值为1
OK
127.0.0.1:6379> incr k1 # k1自增1(相当于++)
(integer) 2
127.0.0.1:6379> incr k1
(integer) 3
127.0.0.1:6379> get k1
"3"
127.0.0.1:6379> decr k1 # k1自减1(相当于--)
(integer) 2
127.0.0.1:6379> decr k1
(integer) 1
127.0.0.1:6379> get k1
"1"
127.0.0.1:6379> incrby k1 3 # k1自增3(相当于+=3)
(integer) 4
127.0.0.1:6379> get k1
"4"
127.0.0.1:6379> decrby k1 2 # k1自减2(相当于-=2)
(integer) 2
127.0.0.1:6379> get k1
"2"
        ● getrange/setrange:类似between...and...
                ○ range:范围
127.0.0.1:6379> set k1 abcdef # 初始化k1的值为abcdef
OK
127.0.0.1:6379> get k1
"abcdef"
127.0.0.1:6379> getrange k1 0 -1 # 查询k1全部的值
"abcdef"
127.0.0.1:6379> getrange k1 0 3 # 查询k1的值,范围是下标0~下标3(包含0和3,共
返回4个字符)
"abcd"
127.0.0.1:6379> setrange k1 1 xxx # 替换k1的值,从下标1开始提供为xxx
(integer) 6
127.0.0.1:6379> get k1
"axxxef
        ● setex/setnx
                ○  set with ex pir :添加数据的同时设置生命周期
127.0.0.1:6379> setex k1 5 v1 # 添加k1 v1数据的同时,设置5秒的声明周期
OK
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> get k1
(nil) # 已过期,k1的值v1自动销毁
                ○  set if n ot e x ist :添加数据的时候判断是否已经存在,防止已存在的数据被覆盖掉
127.0.0.1:6379> setnx k1 sun
(integer) 0 # 添加失败,因为k1已经存在
127.0.0.1:6379> get k1
"laosun"
127.0.0.1:6379> setnx k2 sun
(integer) 1 # k2不存在,所以添加成功
        ● mset/mget/msetnx
        ● m: more 更多
127.0.0.1:6379> set k1 v1 k2 v2 # set不支持一次添加多条数据
(error) ERR syntax error
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 # mset可以一次添加多条数据
OK
127.0.0.1:6379> keys *
1) "k1"
2) "k2"
3) "k3"
127.0.0.1:6379> mget k2 k3 # 一次获取多条数据
1) "v2"
2) "v3"
127.0.0.1:6379> msetnx k3 v3 k4 v4 # 一次添加多条数据时,如果添加的数据
中有已经存在的,则失败
(integer) 0
127.0.0.1:6379> msetnx k4 v4 k5 v5 # 一次添加多条数据时,如果添加的数据
中都不存在的,则成功
(integer) 1
        ● getset:先get set
127.0.0.1:6379> getset k6 v6
(nil) # 因为没有k6,所以get为null,然后将k6v6的值添加到数据库
127.0.0.1:6379> keys *
1) "k4"
2) "k1"
3) "k2"
4) "k3"
5) "k5"
6) "k6"
127.0.0.1:6379> get k6
"v6"
127.0.0.1:6379> getset k6 vv6 # 先获取k6的值,然后修改k6的值为vv6
"v6"
127.0.0.1:6379> get k6
"vv6"

3.1.2 列表List(未完待续......)

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。