Redis复习——事务持久化主从高可用集群

Posted 胖虎是只mao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis复习——事务持久化主从高可用集群相关的知识,希望对你有一定的参考价值。

一、数据类型

  • 字符串
    • set get incr incrby incrby a -1
  • hash {}
    • hset hmset hget hgetall
  • list []
    • lpush rpush lpop rpop
  • set 集合
    • sadd smembers sismember
  • zset (sorted set) 有序集合
    • zadd zscore zrange

redis中的value,可以有多种数据类型,但是每种数据类型不允许嵌套,也就是不能多层使用。每种数据类型中,只能是字符串只是对单一的字符串进行了一次封装,组成了多种类型

{
	'a':  'xxx',
	'b':  {"foo": "100", "":"", xx},
	'c': ["", "","" ],  有序  可以重复
	'd': set(),  无序   不重复
	'e': zset()  有序     值不重复  分数可以相同
			值:权重 分数score
			"itcast": 19  "python":100 "tbd39": 100
			"itcast": 0  "python":0 "tbd39": 0  相同为0 排序按值的字符顺序,—————字母的先后顺序
}

zset (sorted set) redis 会按照权重(分数),由小到大进行排列

只对数据记录级别设置有效期 不对内部的具体元素设置。只能让记录过期

setex 只对字符串类型生效

expires 对所有类型通用

二、redis 事务

基本事务指令
Redis提供了一定的事务支持,可以保证一组操作原子执行不被打断,但是如果执行中出现错误,事务不能回滚,Redis未提供回滚支持

  • multi 开启事务
  • exec 执行事务
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set a 100
QUEUED				// 表示被添加到队列中,其实并没有执行
127.0.0.1:6379> set b 200
QUEUED
127.0.0.1:6379> get a
QUEUED
127.0.0.1:6379> get b
QUEUED
127.0.0.1:6379> exec			// 开始执行
1) OK
2) OK
3) "100"
4) "200"

使用multi开启事务后,操作的指令并未立即执行,而是被redis记录在队列中,等待一起执行。当执行exec命令后,开始执行事务指令,最终得到每条指令的结果

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set c 300
QUEUED
127.0.0.1:6379> hgetall a
QUEUED
127.0.0.1:6379> set d 400
QUEUED
127.0.0.1:6379> get d
QUEUED
127.0.0.1:6379> exec
1) OK
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
3) OK
4) "400"
127.0.0.1:6379>

如果事务中出现了错误,事务并不会终止执行,而是只会记录下这条错误的信息,并继续执行后面的指令。所以事务中出错不会影响后续指令的执行

三、Python客户端操作

在Redis的Python 客户端库redis-py中,提供了pipeline (称为流水线 或 管道),该工具的作用是:

  • 在客户端统一收集操作指令
  • 补充上multi和exec指令,当作一个事务发送到redis服务器执行
from redis import StrictRedis
r = StrictRedis.from_url('redis://127.0.0.1:6381/0')			// 链接对象
pl = r.pipeline()			// 事务已经包含在内
pl.set('a', 100)			// 将这些指令放入管道
pl.set('b', 200)
pl.get('a')
pl.get('b')
ret = pl.execute()			// 指令一次性执行
print(ret) #  [True, True, b'100', b'200']
watch监视

exec执行前,提前发现错误语句,进行终止。跟乐观锁的作用一样
若在构建的redis事务在执行时依赖某些值,可以使用watch对数据值进行监视。

127.0.0.1:6379> set stock 100
OK
127.0.0.1:6379> watch stock		// 监视stock
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incrby stock -1
QUEUED
127.0.0.1:6379> incr sales
QUEUED
127.0.0.1:6379> exec
1) (integer) 99
2) (integer) 1

事务开始到exec执行前,没有任何人对stock值进行改变
事务exec执行前被监视的stock值未变化,事务正确执行。

127.0.0.1:6379> set stock 100
OK
127.0.0.1:6379> watch stock		// 进行监视
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incrby stock -1
QUEUED
127.0.0.1:6379> incr sales
QUEUED

并发情况下,此时在另一个客户端修改stock的值,执行

127.0.0.1:6379> incrby stock -2
(integer) 98

当第一个客户端再执行exec时

127.0.0.1:6379> exec
(nil)

表明事务需要监视的stock值发生了变化,事务不能执行了。

注意:Redis Cluster 集群不支持事务,multi和exec、watch指令只能在单机的方式里用

四、 Redis持久化

redis可以将数据写入到磁盘中,在停机或宕机后,再次启动redis时,将磁盘中的备份数据加载到内存中恢复使用。这是redis的持久化。持久化有如下两种机制。

redis 会在redis程序运行期间,不定期的将保存在内存中的数据写入磁盘里,当作磁盘文件存储起来

redis默认单进程单线程

RDB 快照持久化

redis可以将内存中的数据写入磁盘进行持久化。在进行持久化时,redis会创建子进程来执行

类似于拍一张快照,将数据原封不动全量写入磁盘。 持久化是子进程执行的

redis默认开启了快照持久化机制。

进行快照持久化的时机如下

  • 定期触发
    根据执行频率将内存数据定期写入磁盘中
    redis的配置文件
 #   save  
  #
  #   Will save the DB if both the given number of seconds and the given
  #   number of write operations against the DB occurred.
  #
  #   In the example below the behaviour will be to save:
  #   after 900 sec (15 min) if at least 1 key changed
  #   after 300 sec (5 min) if at least 10 keys changed
  #   after 60 sec if at least 10000 keys changed
  #
  #   Note: you can disable saving completely by commenting out all "save" lines.
  #
  #   It is also possible to remove all the previously configured save
  #   points by adding a save directive with a single empty string argument
  #   like in the following example:
  #
  #   save ""     // 关闭自动执行

  save 900 1		//在900s 之内 如果进行了至少一次写操作,那么就会执行一次快照操作,会将内存数据刷到磁盘中
  save 300 10
  save 60 10000

save 900 1 在多少s 只内,至少执行多少次改变操作后,触发一次快照持久化操作

在这里插入图片描述

  • BGSAVE 手动执行命令

    执行BGSAVE命令,手动触发RDB持久化
    在这里插入图片描述

  • SHUTDOWN

    关闭redis时触发

AOF 追加文件持久化(append only file)

redis可以将执行的所有指令追加记录到文件中持久化存储,这是redis的另一种持久化机制。

redis默认未开启AOF机制。

redis可以通过配置如下项开启AOF机制

appendonly yes  # 是否开启AOF
appendfilename "appendonly.aof"  # AOF文件

AOF机制记录操作的时机

# appendfsync always  # 每个操作都写到磁盘中
appendfsync everysec  # 每秒写一次磁盘,默认
# appendfsync no  # 由操作系统决定写入磁盘的时机

在这里插入图片描述

使用AOF机制的缺点是随着时间的流逝,AOF文件会变得很大。但redis可以压缩AOF文件

结合使用

redis允许我们同时使用两种机制,通常情况下我们会设置AOF机制为everysec 每秒写入,则最坏仅会丢失一秒内的数据。

应用场景:

redis保存数据时,如果不保存业务数据,仅仅当作缓存使用,可以关闭全部的持久化方式,性能可以提升

如果需要保存业务数据,就需要开启持久化。

五、 redis 主从

redis本身自带,配置即可

redis 只能是一主多从,不能有多主,但是就下面从,也可以作为主,类似于树
在这里插入图片描述

slaveof 可以自动使某台机器变成从

在这里插入图片描述
② 配置文件中声明

在这里插入图片描述
查看当前机器是主还是从的信息:info Replication
在这里插入图片描述

六、redis 高可用

为了保证redis最大程度上能够使用,redis提供了主从同步+Sentinel哨兵机制。

redis原生提供高可用,依赖于哨兵机制
哨兵只是一段程序

哨兵文件:
在这里插入图片描述
redis 哨兵的作用是 帮助看护主从机器,能够做自动切换

Sentinel 哨兵 (类似于keepalived)

https://redis.io/topics/sentinel

redis提供的哨兵是用来看护redis实例进程的,可以自动进行故障转移,其功能如下:

  • 监控。Sentinel 会不断检查您的主实例和副本实例是否按预期工作。
  • 通知。Sentinel 可以通过 API 通知系统管理员或其他计算机程序,其中一个受监控的 Redis 实例出现问题。
  • 自动故障转移。如果 master 没有按预期工作,Sentinel 可以启动一个故障转移过程,其中一个副本被提升为 master,其他额外的副本被重新配置为使用新的 master,并且使用 Redis 服务器的应用程序会被告知要使用的新地址连接时。
  • 配置提供程序。Sentinel 充当客户端服务发现的权威来源:客户端连接到 Sentinel 以请求负责给定服务的当前 Redis 主节点的地址。如果发生故障转移,Sentinels 将报告新地址。

在redis安装后,会自带sentinel哨兵程序,修改sentinel.conf配置文件

开启哨兵服务之后,python程序对接redis,直接跟哨兵对接,而不再是redis了。哨兵会告知,主从信息

bind 127.0.0.1		//哨兵IP端口
port 26380
daemonize yes	// 以后台守护进程的方式一直运行
logfile /var/log/redis-sentinel.log		// 日志
sentinel monitor mymaster 127.0.0.1 6380 2		// 哨兵守护该IP机器,
sentinel down-after-milliseconds mymaster 30000  	// 心跳的频率  超过3w 毫秒
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000		// 缓冲时间,时间过后若还未恢复,进行故障转移
  • sentinel monitor mymaster 127.0.0.1 6380 2 说明
    mymaster 为sentinel监护的redis主从集群起名
    127.0.0.1 6300 为主从中任一台机器地址
    2 表示有两台以上的sentinel认为某一台redis宕机后,才会进行自动故障转移,防止因为哨兵自身问题,导致自动故障转移,需要多数哨兵认为才行。

启动方式:

redis-sentinel sentinel.conf

master对外通讯用6379 端口,但是对内,和哨兵通讯时用其他端口,如:16379

			 slave1 -> master   6379   16379->sentinel1  心跳机制
			 |
  sentienl2   slave2    master->slave (sentinel3)
        |
   slave3  slave4 
高可用方案注意事项
  • 至少三个sentinel以上
  • sentinel要分散运行在不同的机器上。保证哨兵不会全部崩溃
Python客户端使用
# redis 哨兵
REDIS_SENTINELS = [
    ('127.0.0.1', '26380'),
    ('127.0.0.1', '26381'),
    ('127.0.0.1', '26382'),
]
REDIS_SENTINEL_SERVICE_NAME = 'mymaster'

from redis.sentinel import Sentinel
_sentinel = Sentinel(REDIS_SENTINELS)		// 直接操作sentinel 哨兵即可,可以直接从上面三太机器中,创建 主 从机器。具体主从分配方式,由redsi自身决定
redis_master = _sentinel.master_for(REDIS_SENTINEL_SERVICE_NAME)		// 获取redis 客户端  从该集群中拿出主
redis_slave = _sentinel.slave_for(REDIS_SENTINEL_SERVICE_NAME)			//// 获取redis 客户端  从该集群中拿出从

使用示例

写数据,只能在master里写,不能在slave中写

# 读数据,master读不到去slave读
try:
    real_code = redis_master.get(key)
except ConnectionError as e:
    real_code = redis_slave.get(key)

# 写数据,只能在master里写
try:
    current_app.redis_master.delete(key)
except ConnectionError as e:
    logger.error(e)

七、 redis集群

https://redis.io/topics/partitioning

Reids Cluster集群方案,内部已经集成了sentinel机制来做到高可用。

数据分片的逻辑:客户端数据存放到主服务器上时,不需要指定哪台,redis自身会根据传入数据的 hash和槽位 进行数学计算,

在这里插入图片描述

开启redis实例之后,执行redis-trib.rb 文件,可以将多台redis实例,组成一个集群。具体,如何组成,有redis自身内部进行决定

在这里插入图片描述

redis-cluster-py python redis集群扩展包

pip install redis-cluster-py
Python客户端
# redis 集群
REDIS_CLUSTER = [
    {'host': '127.0.0.1', 'port': '7000'},
    {'host': '127.0.0.1', 'port': '7001'},
    {'host': '127.0.0.1', 'port': '7002'},
]
# 将开启的机器随机配置几台,放到这边即可,redis会根据这几台机器,找到其他开启的全部机器,并区分主从
from rediscluster import StrictRedisCluster
redis_cluster = StrictRedisCluster(startup_nodes=REDIS_CLUSTER)


# 可以将redis_cluster就当作普通的redis客户端使用
redis_master.delete(key)

链接集群的方式和存储数据的槽位

在这里插入图片描述

注意:

  • redis cluster 不支持事务
  • redis cluster 不支持多键操作,如mset
5 用途
  • 缓存
  • 持久存储
    数据库的统计冗余字段 放到 redis中保存

以上是关于Redis复习——事务持久化主从高可用集群的主要内容,如果未能解决你的问题,请参考以下文章

浅谈小白如何读懂Redis高速缓存与持久化并存及主从高可用集群

浅谈小白如何读懂Redis高速缓存与持久化并存及主从高可用集群

聊聊 Redis 主从同步

redis如何实现高可用主从复制哨兵机制

Redis技术专题「高可用技术基础」一同分析一下Redis高可用的“基石”之主从架构的本质原理解析

Redis——Redis高可用持久化及性能管理