redis笔记

1.NoSQL入门和概述

1.1 为什么使用NoSQL

单机MySQL的的美好年代

​ 在90年代,一个网站的访问量一般都不大,用单个数据库完全可以轻松应付。在那个时候,更多的都是静态网页,动态交互类型的网站不多。

Memcached(缓存)+MySQL+垂直拆分

​ 随着访问量的上升,几乎大部分使用Mysql架构的网站在数据库上都开始了性能问题,web程序不再仅仅专注在功能上,同时也在追求性能。程序员们开始大量的使用缓存计数来缓解数据库的压力,优化数据库的结构和索引。

MySQL主从读写分离

​ 由于数据库的写入压力增加,Memcached只能缓解数据库的读取压力。读写集中在一个数据库上让数据库不堪重负,大部分网站开始使用主从复制技术来达到读写分离,以提高读写性能和读库的可扩展性,MySQL的master-slave模式成为这个时候的网站标配。

分表分库+水平拆分+mysql集群

​ 在Memcached的高速缓存,MySQL的主从复制,读写分离的基础之上,这时MySQL主库的写压力开始出现瓶颈,而数据量的持续猛增,由于MyISAM使用表锁,在高并发下会出现验证的锁问题,大量的高并发MySQL应用开始使用InnoDB引擎代替MyISAM。同时,开始流行使用分表分库来缓解写压力和数据增长的扩展问题。

MySQL的扩展性瓶颈

​ MySQL数据库也经常存储一些大文本字段,导致数据库表非常的大,在做数据库恢复的时候就导致非常的慢,不容易快速恢复数据库。比如1000万4KB大小的文本就接近40GB的大小,如果能把这些数据从MySQL省去,MySQL将变的非常小。关系数据库很强大, 但是它并不是很好的应付所有的应用场景MySQL的扩展性差,大数据下IO压力大,表结构更改困难。

1.2 是什么

NoSQL(Not Only SQL),意即"不仅仅是SQL",泛指非关系型的数据库。

1.3 3V+3高

海量Volume + 多样Variety + 实时Velocity

高并发 + 高可扩 + 高性能

1.4 NoSQL数据库的四大分类

KV键值:Redis

文档型数据库:MongoDB

列存储数据库:HBase

图存储数据库:Neo4J

四者对比

在这里插入图片描述

1.5 CAP + BASE

传统的ACID

A(Atomicity)原子性 + C(Consistency)一致性 + I(Isolation)独立性 + D(Durability)持久性

CAP

C(Consistency)强一致性 + A(Availability)可用性 + P(Partition tolerance)分区容错性

CAP的3进2

CAP理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求,最多只能同时较好的满足两个

因此,根据CAP原理将NoSQL数据库分成了满足CA原则,满足CP原则和满足AP原则三大类:

  • CA - 单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大;(传统Oracle数据库)
  • CP - 满足一致性,分区容错性的系统,通常性能不是特别高;(Redis、Mongodb)
  • AP - 满足可用性,分区容忍性的系统,通常可能对一致性要求低一些。(大多数网站架构的选择)
BASE

BASE就是为了解决关系数据库强一致性引起的问题而引起的可用性降低而提出的解决方案。

  • 基本可用(Basically Available)
  • 软状态(Soft state)
  • 最终一致(Eventually consistent)

它的思想是通过让系统放松对某一时刻数据一致性的要求来换取系统整体伸缩性和性能上改观。

分布式+集群
  • 分布式:不同的多台服务器上面部署不同的服务模块(工程)

  • 集群:不同的多态服务器上面部署相同的服务模块

2.Redis入门介绍

2.1入门概述

Redis:Remote Dictionary Server(远程字典服务器)

​ 是完全开源免费的,用C语言编写的,遵守BSD协议,是一个高性能的(key/value)分布式内存数据库,基于内存运行并支持持久化的NoSQL数据库,是当前最热门的NoSQL数据库之一,也被人们称为数据结构 服务器 。

简单应用场景
  • 内存存储和持久化:redis支持异步将内存中的数据写到硬盘上,同时不影响继续服务
  • 取最新N个数据的操作,如:可以将最新的10条评论的ID放在Redis的List集合里面
  • 模拟类似与HttpSession这种需要设定过期时间的功能
  • 发布、订阅消息系统
  • 定时器、计数器
相关网址

中文网站http://www.redis.cn/

英文网站https://redis.io/

文档http://redisdoc.com/

相关操作
  • 数据类型、基本操作和配置
  • 持久化和复制,RDB/AOF
  • 事务的控制
  • 复制

2.2Redis的安装

测试环境 ubuntu-18.04.1、测试安装路径/opt/

安装GCC编译器 https://www.linuxidc.com/Linux/2019-06/159059.htm

Redis安装 https://www.cnblogs.com/tongongV/p/10927913.html

#更新包列表
sudo apt update
#该命令将安装一堆新包,包括gcc,g ++和make
sudo apt install build-essential
#测试是否成功
gcc --version

Redis的安装、卸载、启动、关闭 https://www.cnblogs.com/tongongV/p/10927913.html

#认识2个目录
#/opt目录用来安装附加软件包,是用户级的程序目录
#/usr/local/bin用户放置自己的可执行程序的地方
cd /opt
wget http://download.redis.io/releases/redis-5.0.5.tar.gz
tar xzf redis-5.0.5.tar.gz
#若在这一步安装gcc后 make distclean
make test
sudo make install
#安装完成后 /opt/redis-5.0.5/src/ 和 /usr/local/bin/ 都有redis相关编译命令
测试

在这里插入图片描述

2.3 Redis的Helloworld

在这里插入图片描述

修改配置文件

在这里插入图片描述

2.4启动后的基础知识

  • 单进程
  • 默认数据库个数16,用select来切换
  • keys k?keys * 获取当前库的key
  • dbsize查看当前库的key的数量
  • flushdb 删当前库,flushall删所有库
  • 索引都是从0开始

3.Redis常用数据类型

3.1基础命令

#删除key
del key
#key是否存在
exists key
#设置过期时间,单位秒
expire key second
#返回过期剩余时间,-1永久,-2失效(key已不存在,get不到)
ttl key
#移除过期时间,设置为永久
persist key
#随机返回一个key
randomkey
#修改key的名称
rename key newkey
#key存储的值的类型
type key

3.2 String(字符串)

String类型是redis最基本的类型,一个key对应一个value,String类型是二进制安全的,一个redis中字符串value最多512M。

#set
set key value
#set if not exists 当key不存在时设置key
setnx key value
#设置key,并设置过期时间
setex key second value
#get
get key
#获取key对应的value 从start开始,end结束
getrange key start end
#设置key 从offset开始value覆盖原先的数据
setrange key offset value
#获取多个key
mget key [key...]
#先get然后再set,无论是否存在key都会set,没有key的话get的值为nil
getset key value
#获取长度
strlen key
#value(必须为常数,否则返回error)的值+1,不存在key则新增key value=1,
incr key  ----  decr key 
#同上,但是增量为increment
incrby key increment  ----  decrby key decrement  ---- incrbyfloat key increment(增量为小数)

应用场景:String通常用户保存单个字符串或JSON字符串数据;

因为String是二进制安全的,所以可以把保密要求高的图片文件内容作为字符串来存储;

计数器:常规key-value缓存应用,如粉丝数,incr本身具有原子性特性,所以不会有线程安全。

3.3 Hash(哈希)

是一个键值对集合,适合用户存储对象,可以看成field和value的map容器

#设置key设定filed-value ,如hmset user name zhangsan age 18,类似java里的user对象
hset key field value
hmset key field value [filed value...]
#当field不存在时,设置field-value
hsetnx key field value
#获取field的value
hget key field
hmget key field [key field...]
#返回key所有的field和value
hgetall key
#key所有的field
hkeys key
#key所有的value
hvals key
#key的field数量
hlen key
#删除field
hdel key field [field...]
#是否存在field
hexists key field
#增量为increment 增加field
hincrby key filed increment

应用场景:通常用来存储一个用户信息的对象数据;

3.4 List(列表)

#左边插入
lpush key value [value...]
#右边插入
rpush key value [value...]
#获取指定范围的元素 0 -1
lrange key start end
#插入,若key不存在,不操作
lpushx key value [value...]
rpush key value [value...]
#获取列表长度
llen key
#从下标0开始获取元素
lindex key index
#移除一个元素
lpop key ---- rpop key
#移除count个指定的value
lrem key count value
#移除列表第一个元素,如果没有会阻塞列表到等待超时或发现可弹出元素为止
blpop key [key...] timeout --- brpop key [key...] timeout
#过滤掉只保留start到end之间的元素
ltrim key start end
#设置索引对应的value
lset key index value
#在pivot之前或之后插入value
linsert key before/after pivot value

3.5 Set(集合)

唯一

#添加元素
sadd key member [member...]
#key中元素数量
scard key
#返回key中所有的元素
smembsers key
#判断member 是否 存在key中
sismember key member
#随机返回count个元素
srandmember key [count]
#移除member
srem key member [member...]
#随机移除count个元素
spop key [count]
#从source移动一个member到destination
smove source destination member
#差集 返回key1中有的key2中没有的
sdiff key1 key2 [key...]
#将差集存储到destination
sdiffstore destination key1 key2 [key...]
#交集
sinter key1 key2 [key...]
#并集
sunion key1 key2

3.6 Zset(sorted set 有序集合)

#添加
zadd key score member [score member...]
#返回集合中的元素数量
zcard key
#获取min-max之间的score的个数
zcount key min max
#获取下标从start到end之间的元素 默认输出member 要输出score(withscores)
zrange key start end [withscores]
#获取min-max之间的score的元素
zrangebyscore key min max [withscores]
#返回member的下标
zrank key member
#返回范围内分数从高到低的元素 与 zrange key start end 相反
zrevrange key start end [withscores]
#移除member元素
zrem key member [member]
#移除下标start-end的元素
zremrangebyrank key start end
#移除分数范围内的元素
zremrangebyscore key min max

4.持久化

4.1RDB

​ Redis DataBase:在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读到内存中。

​ Redis会单独创建一个(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能。如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。

fork

​ fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量,环境变量,程序计数器等)数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程。

配置文件
#	下列行为中将自动save
#   In the example below the behaviour will be to save:
#900秒内改变一次
save 900 1
#300秒内改变10次
save 300 10
#60秒内该变10000次
save 60 10000

# 转储数据库rbd的文件名
# The filename where to dump the DB
dbfilename dump.rdb

# 此处指定目录 默认./表示/usr/local/bin/(同安装的编译路径)
# Note that you must specify a directory here, not a file name.
dir ./

# 如果配置成no,表示你不在乎数据不一致或者有其他的手段发现和控制
# However if you have setup your proper monitoring of the Redis server
# and persistence, you may want to disable this feature so that Redis will
# continue to work as usual even if there are problems with disk,
# permissions, and so forth.
stop-writes-on-bgsave-error yes

# 对于存储到磁盘中的快照,可以设置是否进行压缩存储。如果是,redis会采用LZF算法进行压缩,如果不想消耗CPU来进行压缩的话,可以关# 闭此功能
# Compress string objects using LZF when dump .rdb databases?
# For default that's set to 'yes' as it's almost always a win.
# If you want to save some CPU in the saving child set it to 'no' but
# the dataset will likely be bigger if you have compressible values or keys.
rdbcompression yes

# 在存储快照后,还可以让redis使用CRC64算法来进行数据校验,但是这样会增加大约10%的性能消耗,如果希望获取到最大的性能提升,可以# 关闭
# RDB files created with checksum disabled have a checksum of zero that will
# tell the loading code to skip the check.
rdbchecksum yes
触发RDB快照
# 1.配置文件中默认的快照配置
# 2.save和bgsave
# save只管保存,其他不管,全部阻塞
# bgsave:redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。可以通过lastsve获得最后一次成功执行快照的时间。
# 3. flushall命令,产生dump.rdb文件,但无意义,因为是空文件。
如何恢复

​ 将备份文件dump.rdb移动到redis安装目录启动服务即可

优势
  • 适合大规模的数据恢复
  • 对数据完整性和一致性要求不高
劣势
  • 在一定间隔时间做一次备份,如果redis意外down掉的话,就会丢失最后一次快照后的所有修改
  • fork的时候,内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑

4.2 AOF

以日记的形式来记录每个写操作,将Redis执行过的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读写改文件重新构建数据,换言之,redis重启的话就根据日志文件的内容将写执行从前到后执行一次以完成数据的恢复工作。

配置文件
# 开启aop持久化方式
appendonly yes

# 文件名
# The name of the append only file (default: "appendonly.aof")
appendfilename "appendonly.aof"

# always:同步持久化,每次发生数据变更会被立即记录到磁盘,性能较差但数据完整性较好
# everysec:出厂默认推荐,异步操作,每秒记录。如果一秒内宕机,有数据丢失
# no
appendfsync everysec

# rewrite
# aof采用文件追加方式,文件会越来越大为避免出现此种情况,新增了重写机制,当aof文件的大小超过所设置的阈值时,redis就会启动aof文件的内容压缩,只保留可以恢复数据的最小指令集,可以使用命令bgrewriteaof
# redis会记录上次重写时的aof大小,默认配置是当aof文件大小是上次rewrite后大小的一倍且文件大于64M时触发
# 重写时是否可以运用appendfsync ,用默认no即可,保证数据安全性
no-appendfsync-no-rewrite no
# 设置重写的基准值
auto-aof-rewrite-percentage 100
# 设置重写的基准值
auto-aof-rewrite-min-size 64mb
如何恢复

​ 同rdb,设置appendonly yes后aof文件优先级比rdb文件大

修复aof文件
redis-check-aof --fix appendonly.aof
优势
  • 每秒同步:appendfsync always
  • 修改同步:appendfsync everysec
  • 不同步:appendfsync no
劣势
  • 相同数据集的数据而言aof文件要远大鱼rdb文件,恢复速度慢于rdb
  • aof运行速率要慢于rdb,每秒同步策略效率较好,不同步效率和rdb相同

4.3 总结

​ 如果你只希望你的数据在服务器运行的时候存在,可以不使用任何的持久化方式。

​ 一般建议同时开启两种持久化方式。AOF进行数据的持久化,确保数据不会丢失太多,而RDB更适合用于备份数据库,留着一个做万一的手段。

性能建议:

​ 因为RDB文件只用做后备用途,建议只在slave上持久化RDB文件,而且只要在15分钟备份一次就够了,只保留900 1这条规则。

​ 如果Enalbe AOF,好处是在最恶劣情况下也只会丢失不超过两秒数据,启动脚本较简单只load自己的AOF文件就可以了。代价:1、带来了持续的IO;2、AOF rewrite的最后将rewrite过程中产生的新数据写到新文件造成的阻塞几乎是不可避免的。只要硬盘许可,应该尽量减少AOF rewrite的频率,AOF重写的基础大小默认值64M太小了,可以设到5G以上。默认超过原大小100%大小时重写可以改到适当的数值。

​ 如果不Enable AOF,仅靠Master-Slave Replication 实现高可用性也可以。能省掉一大笔IO也减少了rewrite时带来的系统波动。代价是如果Master/Slave同时宕掉,会丢失10几分钟的数据,启动脚本也要比较两个Master/Slave中的RDB文件,载入较新的那个。新浪微博就选用了这种架构。

5.事务

5.1定义

​ 可以一次执行多个命令,本质是一组命令的集合。一个事务中的所有命令都会序列化,按顺序的串行执行而不会被其他命令插入,不许加塞。

5.2操作

常用命令
# 取消事务,事务块内的所有命令取消
discard
# 执行事务块内的命令
exec
# 标记事务块的开始
multi
# 取消watch命令对所有key的监视
unwatch
# 监视key,如果在事务执行之前被其他命令改动,事务就被打断
watch key [key...]
悲观锁和乐观锁

​ 类似于表锁和行锁

​ 悲观锁:顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据的就会block直到它拿到锁。传统的关系型数据库里面就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁,都是在操作之前先上锁。

​ 乐观锁:顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新前的时候会判断一下在此此间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,乐观锁策略(提交版本必须大于记录当前版本才能执行更新)

watch监控
  • 正常情况

在这里插入图片描述

  • 无加塞篡改

在这里插入图片描述

  • 有加塞篡改

在这里插入图片描述

  • unwatch取消监视

5.3 三阶段

  • 开启:以MULTI开启一个事务
  • 入队:将多个命令入队到事务中,接到这些命令并不会立即执行,而是放到等待执行的事务队列里面
  • 执行:由EXEC命令触发事务

5.4三特性

  • 单独的隔离操作:事务中的所有命令都是序列化、按顺序的执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
  • 没有隔离级别的概念:队列中的命令没有提交之前都不会实际的被执行,因为事务提交前任何指令都不会被实际执行,也就不存在"事务内的查询要看到事务里的更新,在事务外查询不能看到"这个让人万分头疼的问题。
  • 不保证原子性:redis同一事务中如果有一条命令执行失败,其后的命令任然会被执行,没有回滚。

6.主从复制

6.1定义

​ 也就是我们所说的主从复制,主机数据更新后根据配置和策略,自动同步到备机的master/slaver机制,master以写为主,slave以读为主。

6.2 作用

  • 读写分离
  • 容灾恢复

6.3操作

修改配置文件
  • 拷贝多个redis.conf
  • 开启daemonize yes
  • pid文件名字
  • 指定端口
  • log文件名字
  • dump.rdb名字
  • (appendonly.aof)
从库配置
slaveof 主库ip 主库端口
配置3台机器

在这里插入图片描述

6.4 常用

一主二仆

在这里插入图片描述

  • slave第一次连接是全量复制,之后是增量复制
  • slave与master断开之后,都需要重新连接,除非配置redis.conf文件
  • master断开后,slave待机,等待master重新连接
薪火相传

在这里插入图片描述

反客为主
#使当前数据库转为master,其下连接的slave不断开连接
slaveof no one
哨兵模式

​ 反客为主的自动化,能够后台监控主机是否故障,如果故障了根据投票数自动将从库slave转化为主库master。

# 1.新建sentinel.conf文件
# 2.投票多于1票的转化为master
sentinel monitor 被监控数据库名(自定义名字) 127.0.0.1 6379 1
# 3.执行
redis-sentinel sentinel.conf
复制原理
  • Slave启动成功连接到master后会发送一个sync命令;
  • Master接到命令启动后的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,master将传送整个数据文件到slave,以完成一次完全同步;
  • 全量复制:而slave服务在数据库文件数据后,将其存盘并加载到内存中;
  • 增量复制:Master继续将新的所有收集到的修改命令依次传给slave,完成同步;
  • 但是只要是重新连接master,一次完全同步(全量复制)将被自动执行。
复制缺点

​ 延时,由于所有的写操作都是在Master上操作,然后同步更新到Slave上,所以从Master同步到Slave机器有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,Slave机器数量的增加也会使得这个问题更加严重。

-------------------------------------------待续

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值