侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

NoSQL数据库之Redis数据库管理(Redis高级应用之事务处理、持久化操作、pub_sub、虚拟内存)

Redis  /  管理员 发布于 3年前   284

3.事务处理

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

redis 127.0.0.1:6379> get age"33"redis 127.0.0.1:6379> multiOKredis 127.0.0.1:6379> set age 10QUEUEDredis 127.0.0.1:6379> set age 20QUEUEDredis 127.0.0.1:6379> exec1) OK2) OKredis 127.0.0.1:6379> get age"20"

        如何取消一个事务

redis 127.0.0.1:6379> get age"20"redis 127.0.0.1:6379> multiOKredis 127.0.0.1:6379> set age 30QUEUEDredis 127.0.0.1:6379> set age 40QUEUEDredis 127.0.0.1:6379> discardOKredis 127.0.0.1:6379> get age"20"

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

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

redis 127.0.0.1:6379> incr name(error) ERR value is not an integer or out of rangeredis 127.0.0.1:6379> multiOKredis 127.0.0.1:6379> incr ageQUEUEDredis 127.0.0.1:6379> incr nameQUEUEDredis 127.0.0.1:6379> exec1) (integer) 212) (error) ERR value is not an integer or out of rangeredis 127.0.0.1:6379> get age"21"

        乐观锁复杂事务控制:

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

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

        1)第1步 session1

redis 127.0.0.1:6379> get age"10"redis 127.0.0.1:6379> watch ageOKredis 127.0.0.1:6379> multiOK

        2)第2步 session2

redis 127.0.0.1:6379> set age 30OKredis 127.0.0.1:6379> get age"30"

        3)第3步 session1

redis 127.0.0.1:6379> set age 30QUEUEDredis 127.0.0.1:6379> exec(nil)  //因为有wathch ageredis 127.0.0.1:6379> get age"30"

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

        事务回滚:redis的事务实现是如此简单,当然会存在一些问题。第一个问题是redis只能保证事务的每个命令连续执行,但是如果事务中的一个命令失败了,并不回滚其他命令,比如使用的命令类型不匹配。

 

4.持久化机制

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

        Redis支持两种持久化方式:

        a.snapshotting(快照)也是默认方式

        b.Append-only file(缩写aof)的方式

        1).Snapshotting方式

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

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

        2).aof方式

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

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

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

        可以通过配置文件告诉redis我们想要通过fsync函数强制os写入到磁盘的时机,默认的文件名为appendonly.aof[可通过cat方法看,保存的是命令]。

        vi /usr/local/redis/etc/redis.conf

appendonly yes //启动aof持久化方式#appendfsync always  //收到写命令就立即写入磁盘,最慢,但是保证完全的持久化appendfsync everysec //每秒种写入磁盘一次,在性能和持久化方面做了很好的折中#appendfsync no //完全依赖os,性能最好,持久化没保证

 

5.发布订阅消息

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

        1)第1步 session1

redis 127.0.0.1:6379> subscribe tv1 tv2Reading message... (press Ctrl+C to quit)1) "subscribe"2) "tv1"3) (integer) 11) "subscribe"2) "tv2"3) (integer) 2

        2)第2步 session2

redis 127.0.0.1:6379> subscribe tv1Reading message... (press Ctrl+C to quit)1) "subscribe"2) "tv1"3) (integer) 1

        3)第3步 session3

redis 127.0.0.1:6379> publish tv1 test(integer) 2  //说明有两个监听redis 127.0.0.1:6379> publish tv2 haha(integer) 1  //说明只有一个监听redis 127.0.0.1:6379> 

        4)第4步 session1

1) "message"2) "tv1"3) "test"1) "message"2) "tv2"3) "haha"

        第4步 session2

1) "message"2) "tv1"3) "test"

 

6.虚拟内存的使用

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

        下面是vm相关配置:

         vi  /usr/local/redis/etc/redis.conf

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对象换入的工作线程数量

        并设置如下配置,确定要使用虚拟内存

really-use-vm yes

 

说明:本文是我网上学习LAMP兄弟连李捷老师《NoSQL数据库之Redis数据库管理》的学习笔记。


  • 上一条:
    NoSQL数据库之Redis数据库管理(Redis的常用命令及高级应用)
    下一条:
    【Redis二】Redis2.8.17搭建主从复制环境
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • Redis集群之主从复制错误:NOAUTH Authentication required解决方式(0个评论)
    • redis数据同步工具redis-shake之两服务器之间数据实时同步案例(0个评论)
    • redis中INCR、SETNX、SET三种加锁方式详解(0个评论)
    • redis安全配置之修改端口、添加密码流程步骤及启动使用(0个评论)
    • redis实现分页(0个评论)
    • 近期文章
    • 如何优雅处理async await错误推荐:await-to-js库(0个评论)
    • lodash工具库(0个评论)
    • 在Laravel项目中使用中间件方式统计用户在线时长功能代码示例(0个评论)
    • 在Laravel中构建业务流程模型(0个评论)
    • windows系统中安装FFMpeg及在phpstudy环境php7.3 + php-ffmpeg扩展的使用流程步骤(0个评论)
    • 在go语言中对浮点的数组、切片(slice)进行正向排序和反向排序(0个评论)
    • 在go语言中对整数数组、切片(slice)进行排序和反向排序(0个评论)
    • 在go语言中对字符串数组、切片(slice)进行排序和反向排序(0个评论)
    • 最新国内免注册ChatGPT体验站_ChatGPT镜像站访问链接地址2023/3/28持续更新(0个评论)
    • 在Laravel项目中的实现无密码认证之:发送邮箱链接授权(0个评论)
    • 近期评论
    • 博主 在

      2023年国务院办公厅春节放假通知:1月21日起休7天中评论 @ xiaoB 你只管努力,剩下的叫给天意;天若有情天亦老,..
    • xiaoB 在

      2023年国务院办公厅春节放假通知:1月21日起休7天中评论 会不会春节放假后又阳一次?..
    • BUG4 在

      你翻墙过吗?国内使用vpn翻墙可能会被网警抓,你需了解的事中评论 不是吧?..
    • 博主 在

      go语言+beego框架中获取get,post请求的所有参数中评论 @ t1  直接在router.go文件中配就ok..
    • Jade 在

      如何在MySQL查询中获得当月记录中评论 Dear zongscan.com team, We can skyroc..
    • 2017-12
    • 2020-03
    • 2020-05
    • 2021-04
    • 2022-03
    • 2022-05
    • 2022-08
    • 2023-02
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客