07_NoSQL数据库之Redis数据库:Redis的高级应用之事务处理、持久化操作、pub_sub、虚拟内存

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介:  事务处理 Redis对事务的支持目前还比较简单。Redis只能保证一个client发起的事务中的命令可以连续的执行,而中间不会插入其他client的命令。当一个client在一个连接中发出multi命令时,这个连接会进入一个事务上下文,该连接后续的命令不会立即执行,而是先放到一个队列中,当执行exec命令时,redis会顺序的执行队列中的所有命令。

  1. 事务处理

Redis对事务的支持目前还比较简单。Redis只能保证一个client发起的事务中的命令可以连续的执行,而中间不会插入其他client的命令。当一个client在一个连接中发出multi命令时,这个连接会进入一个事务上下文,该连接后续的命令不会立即执行,而是先放到一个队列中,当执行exec命令时,redis会顺序的执行队列中的所有命令。

127.0.0.1:6379> get age

(nil)

127.0.0.1:6379> multi

OK                      //表示事务开始

127.0.0.1:6379> set age 10

QUEUED                  //表示放入队列

127.0.0.1:6379> set age 20

QUEUED                  //表示这两个都放入队列中了

127.0.0.1:6379> exec        //分别分别返回两条命令的结果

1) OK                     

2) OK

127.0.0.1:6379> get age

"20"

127.0.0.1:6379>

 

A:取消一个事务,使用discard

127.0.0.1:6379> get age

"20"

127.0.0.1:6379> multi

OK

127.0.0.1:6379> set age 30

QUEUED

127.0.0.1:6379> set age 40

QUEUED

127.0.0.1:6379> discard

OK

127.0.0.1:6379> get age

"20"

127.0.0.1:6379>

可以发现这次2set age命令都没被执行。Discard命令其实就是清空事务的命令队列并退出事务上下文,也就是我们常说的事务回滚。

 

B.乐观锁:大多数是基于数据版本(version)的记录机制实现的。即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过数据库表添加一个“version”字段来实现读取出数据时,将此版本号一同读出,之后更新时,对此版本号加1。此时,将提交数据的版本号与数据库表对应记录的当前版本号进行比对,如果提交的数据版本号大于数据库当前版本号,则予以更新,否则认为是过期数据。

 

Redis乐观锁实例:假设一个agekey,我们开2session来对age进行赋值操作,我们来看一下结果如何。

 

watch命令会监视给定的key,当exec时候如果监视的key从调用watch后发生过变化,则整个事务会失败。也可以调用watch多次监视多个key。这样就可以对指定的key加乐观锁了,注意watchkey是对整个连接有效的,事务也一样。如果连接断开,监视和事务都会被自动清除。当然了execdiscard,unwatch命令都会清除连接中的所有监视。

127.0.0.1:6379> get age

"20"

127.0.0.1:6379> get name

(nil)

127.0.0.1:6379> set name toto

OK

127.0.0.1:6379> multi

OK

127.0.0.1:6379> incr age

QUEUED

127.0.0.1:6379> incr name

QUEUED

127.0.0.1:6379> exec

1) (integer) 21              //可以看到事务并没有回滚,执行了一条,后面一条失败

2) (error) ERR value is not an integer or out of range

127.0.0.1:6379> get age

"21"

127.0.0.1:6379> get name

"toto"

127.0.0.1:6379>

从这个例子中可以看到,age由于是个数字,那么它可以有自增运算,但是name是个字符串,无法对其进行自增运算,所以会报错,如果按传统关系型数据库的思路来讲,整个事务都会回滚,但是我们看到redis却是将可以执行的命令提交了,所以这个现象对于习惯关系型数据库操作的朋友来说是很别扭的,这一点也是redis今天需要改进的地方。

 

持久化机制

Redis是一个支持持久化的内存数据库,也就是说redis需要经常讲内存中的数据同步到硬盘来保证持久化。Redis支持两种持久化方式:

  1. snapshotting(快照)也是默认方式。(也就是说把数据做一个备份)

  2. append-only file(缩写aof)的方式。(将写和更改删除等操作放到文件中)。

 

快照是默认的持久化方式。这种方式是将内存中数据以快照的方式写入到二进制文件中。默认的文件名为dump.rdb。可以通过配置自动做快照持久化的方式。我们可以配置redisn秒内如果超过mkey被修改就自动做快照。

save 900 1 #900秒内如果超过1key被修改,则发起快照保存

save 300 10 #300秒内容如超过10key被修改,则发起快照保存

save 60 10000

rdb所在位置:

默认开启的配置是:

 

aof方式:

由于快照方式是在一定间隔时间做一次的,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改。

aof比快照方式更好的持久性,是由于在使用aof时,redis会将每一个收到的写命令都通过write函数追加到文件中,当redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。

当然由于os会在内核中缓存write做的修改,所以可能不是立即写到磁盘上。这样aof方式的持久化也还是有可能丢失部分修改。

可以通过配置文件告诉redis我们想要通过fsync函数强制os写入到磁盘的时机。

appendonly yes   //启动aof持久化方式

# appendfsync always   //收到写命令就立即写入磁盘,最慢,但是保证完全的持久化。(表示每次写都会往文件中写一次)

appendfsync everysec   //每秒钟写入磁盘一次,在性能和持久化方面做了很好的折中。(表示每秒都会执行一次)

#appendfsync no       //完全依赖os,性能最好,持久化没保证

要修改的配置文件是:vim /usr/local/redis/etc/redis.conf

appendonly的默认参数是no,我们可以给它改成yes

修改同步方式:

重新启动服务器:/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf

测试运行

[toto@localhost ~]$ /usr/local/redis/bin/redis-cli

127.0.0.1:6379> set name toto1

(error) NOAUTH Authentication required.

127.0.0.1:6379> auth toto

OK

127.0.0.1:6379> set name toto1

OK

127.0.0.1:6379> exit

[toto@localhost ~]$ ll

总用量 60

drwxrwxr-x. 2 toto toto 4096 10 16 19:09 1016

-rw-r--r--. 1 toto toto   57 2  15 15:59 appendonly.aof

-rw-rw-r--. 1 toto toto   38 2  15 15:56 dump.rdb

drwxr-xr-x. 3 root root 4096 10 13 16:34 mysql

drwxrwxr-x. 3 toto toto 4096 2   6 17:24 redis

drwxrwxr-x. 2 toto toto 4096 1  31 19:58 server

drwxrwxr-x. 3 toto toto 4096 10 16 19:02 shell

drwxr-xr-x. 2 toto toto 4096 10 16 08:58 公共的

drwxr-xr-x. 2 toto toto 4096 10 16 08:58 模板

drwxr-xr-x. 2 toto toto 4096 10 16 08:58 视频

drwxr-xr-x. 2 toto toto 4096 10 16 08:58 图片

drwxr-xr-x. 2 toto toto 4096 10 16 08:58 文档

drwxr-xr-x. 2 toto toto 4096 10 16 08:58 下载

drwxr-xr-x. 2 toto toto 4096 10 16 08:58 音乐

drwxr-xr-x. 2 toto toto 4096 10 16 10:07 桌面

[toto@localhost ~]$ ls

1016  appendonly.aof  dump.rdb  mysql  redis  server  shell  公共的  模板  视频  图片  文档  下载  音乐  桌面

[toto@localhost ~]$ cat appendonly.aof

*2

$6

SELECT

$1

0

*3

$3

set

$4

name

$5

toto1

*3

$3

set

$4

name

$5

toto2

[toto@localhost ~]$

由上可以知道aof文件中存的是写命令。

 

 

发布及订阅消息

    发布订阅(pub/sub)是一种消息通信模式,主要的目的是解除消息发布者和消息订阅者之间的耦合,Redis作为一个pub/subserver,在订阅者和发布者之间起到了消息路由的功能。订阅者可以通过subscribepsubscribe命令向redis server订阅自己感兴趣的消息类型,redis将信息类型称为通道(channel.当发布者通过publish命令向redis server发送特定类型的信息时,订阅信息类型的全部client都会收到此消息。

实验步骤:

打开三个客户端:

分别使用:/usr/local/redis/bin/redis-cli -a toto登录客户端

 

在第一个客户端输入:subscribe tv1   通过这种方式监听tv1频道

在第二个客户端输入:subscribe tv1 tv2 通过这种方式监听tv1,tv2频道

在第三个客户端通过public命令发布消息,输入:以下命令:

 

这样,在第一个客户端和第二个客户端中会监听到第三个客户端发布的消息,最后的输出如下:

客户端一的消息如下:

客户端二的消息如下:

 

应用:做消息系统和聊天系统

 

虚拟内存的使用:

   Redis的虚拟内存与操作系统的虚拟内存内存不是一回事儿,但是思路和目的都是相同的。就是暂时把不经常访问的数据从内存交换到磁盘中,从而腾出宝贵的内存空间用于其他需要访问的数据。尤其是对于redis这样的内存数据库,内存总是不够用的。除了可以将数据分割到多个redis server外。另外能够提高数据库容量的办法就是使用虚拟内存把那些不经常访问的数据交换到磁盘上。

 

下面是虚拟内存的配置情况:

vm-enabled yes                 #开启vm功能

vm-swap-file /tmp/redis.swap     #交换出来的value保存的文件路径

vm-max-memory 1000000        #redis使用的最大内存上限

vm-page-size 32                #每个页面的大小32字节

vm-pages 134217728            #最多使用多少页面

vm-max-threads 4               #用于执行value对象换入的工作线程数量

 

注意:自己在2.配置的时候上面的参数不可以配置。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
JavaScript 关系型数据库 MySQL
❤Nodejs 第六章(操作本地数据库前置知识优化)
【4月更文挑战第6天】本文介绍了Node.js操作本地数据库的前置配置和优化,包括处理接口跨域的CORS中间件,以及解析请求数据的body-parser、cookie-parser和multer。还讲解了与MySQL数据库交互的两种方式:`createPool`(适用于高并发,通过连接池管理连接)和`createConnection`(适用于低负载)。
19 0
|
14天前
|
存储 安全 搜索推荐
酒店管理系统的数据库的应用以及选择
酒店管理系统数据库关乎运营效率和服务质量。数据库用于数据存储、管理、分析及客户关系管理,确保房态与预订精准。选择时重视性能稳定性、数据安全、易用性、可扩展性和成本效益。合适的数据库能提升酒店运营效率并优化客户体验。
21 2
|
1月前
|
SQL 数据库连接 数据库
你不知道ADo.Net中操作数据库的步骤【超详细整理】
你不知道ADo.Net中操作数据库的步骤【超详细整理】
16 0
|
1天前
|
缓存 NoSQL 关系型数据库
在Python Web开发过程中:数据库与缓存,MySQL和NoSQL数据库的主要差异是什么?
MySQL与NoSQL的主要区别在于数据结构、查询语言和可扩展性。MySQL是关系型数据库,依赖预定义的数据表结构,使用SQL进行复杂查询,适合垂直扩展。而NoSQL提供灵活的存储方式(如JSON、哈希表),无统一查询语言,支持横向扩展,适用于处理大规模、非结构化数据和高并发场景。选择哪种取决于应用需求、数据模型及扩展策略。
10 0
|
7天前
|
NoSQL MongoDB Redis
Python与NoSQL数据库(MongoDB、Redis等)面试问答
【4月更文挑战第16天】本文探讨了Python与NoSQL数据库(如MongoDB、Redis)在面试中的常见问题,包括连接与操作数据库、错误处理、高级特性和缓存策略。重点介绍了使用`pymongo`和`redis`库进行CRUD操作、异常捕获以及数据一致性管理。通过理解这些问题、易错点及避免策略,并结合代码示例,开发者能在面试中展现其技术实力和实践经验。
129 8
Python与NoSQL数据库(MongoDB、Redis等)面试问答
|
9天前
|
存储 数据库连接 数据处理
NumPy与数据库的结合应用探索
【4月更文挑战第17天】本文探讨了NumPy与数据库结合在数据处理和分析中的应用,阐述了结合使用的必要性,包括数据提取、转换、处理与分析及结果存储。通过Python数据库连接库提取数据,转化为NumPy数组进行高效计算,适用于金融等领域的数据分析。结合应用的优势在于高效性、灵活性和可扩展性,但也面临数据转换、性能优化和安全性挑战。
|
16天前
|
存储 传感器 监控
数据库的应用
数据库广泛应用于电子商务、物流、酒店管理、医疗、航空、教育、政府和物联网等领域,用于高效存储和管理商品信息、订单数据、医疗记录、航班详情等各类数据,提升效率和服务质量。随着技术进步,其应用场景将持续扩展。
12 1
|
17天前
|
存储 关系型数据库 MySQL
【mybatis-plus】Springboot+AOP+自定义注解实现多数据源操作(数据源信息存在数据库)
【mybatis-plus】Springboot+AOP+自定义注解实现多数据源操作(数据源信息存在数据库)
|
23天前
|
NoSQL 大数据 数据挖掘
现代数据库技术与大数据应用
随着信息时代的到来,数据量呈指数级增长,对数据库技术提出了前所未有的挑战。本文将介绍现代数据库技术在处理大数据应用中的重要性,并探讨了一些流行的数据库解决方案及其在实际应用中的优势。
|
30天前
|
存储 NoSQL Java
Redis 数据结构操作入门
Redis 数据结构操作入门
15 0