Redis学习笔记五:redis的高级实用特性讲解
Redis学习笔记五:redis的高级实用特性讲解
孟飞阳 发表于1年前
Redis学习笔记五:redis的高级实用特性讲解
  • 发表于 1年前
  • 阅读 1357
  • 收藏 97
  • 点赞 1
  • 评论 4

腾讯云 新注册用户 域名抢购1元起>>>   

一、Redis高级实用特性

1.安全性

        设置客户端连接后进行任何其他指定前需要使用的密码。

        警告:因为redis速度相当快,所以在一台比较好的服务器下,一个外部的用户可以在一秒钟进行150K次的密码尝试,这意味着你需要指定非常强大的密码来防止暴力破解。

[root@localhost ~]# vi /usr/local/redis/etc/redis.conf 

 

        修改配置文件中的如下配置项

1.  #requirepass foobared  
2.  requirepass beijing

        我们设置了连接的口令是beijing。

        重启redis服务

1.  [root@localhost ~]# pkill redis-server  
2.  [root@localhost ~]# /usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf  
3.  [root@localhost ~]# /usr/local/redis/bin/redis-cli  
4.  redis 127.0.0.1:6379> keys *  
5.  (error) ERR operation not permitted  
6.  redis 127.0.0.1:6379> auth beijing  
7.  OK  
8.  redis 127.0.0.1:6379> keys *  
9.  1) "name"  
10. redis 127.0.0.1:6379> exit  
11.   
12. [root@localhost ~]# /usr/local/redis/bin/redis-cli -a beijing  
13. redis 127.0.0.1:6379> keys *  
14. 1) "name" 

 

2.主从复制

        Redis主从复制配置和使用都非常简单。通过主从复制可以允许多个slave server拥有和master server相同的数据库副本。

1).Redis主从复制特点:

        a.Master可以拥有多个slave

        b.多个slave可以连接同一个master外,还可以连接到其它slave

        c.主从复制不会阻塞master,在同步数据时,master可以继续处理client请求

        d.提高系统的伸缩性

2).Redis主从复制过程:

        a.Slave与Master建立连接,发送sync同步命令

        b.Master会启动一个后台进程,将数据库快照保存到文件中,同时Master主进程会开始收集新的写命令并缓存

        c.后台完成保存后,就将此文件发送给slave

        d.Slave将此文件保存到硬盘上

3).配置主从服务器

        配置slave服务器很简单,只需要在slave的配置文件中加入以下配置:

1.  slaveof 192.168.1.1 6379 #指定master的ip和端口   

2.  masterauth beijing #这是主机的密码  

1.  [root@localhost ~]# vi /usr/local/redis/etc/redis.conf  
2.  //修改其中的slaveof <maserip> <masterport>、masterauth <master-password>  
3.  [root@localhost ~]# /usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf  
4.  [root@localhost ~]# /usr/local/redis/bin/redis-cli -a beijing  
5.  redis 127.0.0.1:6379> keys *  
6.  (empty list or set)  

        配置好后,在Master设置任何key,在Slaver数据库中也会有,表示主从复制成功。

        如我们在主数据库上设置一对键值对

1.  redis 127.0.0.1:6379> set name master  
2.  OK  
3.  redis 127.0.0.1:6379>  

        在从数据库上取这个键

1.  redis 127.0.0.1:6379> get name  
2.  "master"  
3.  redis 127.0.0.1:6379>  

        我们怎么判断哪个是主哪个是从呢?我们只需调用info就可以得到主从信息,我们在从库中执行info如下:

1.  redis 127.0.0.1:6379> info  
2.  role:slave  
3.  master_host:localhost  
4.  master_port:6379  
5.  master_link_status:up  
6.  master_last_io_seconds_ago:10  
7.  master_sync_in_progress:0  
8.  db0:key=1,expires=0  
9.  redis 127.0.0.1:6379> 

        里面的role会显示是Master还是Slave服务器,master_link_status的值是up表示正在连接Master服务器

 

3.事务处理

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

1.  redis 127.0.0.1:6379> get age  
2.  "33"  
3.  redis 127.0.0.1:6379> multi  
4.  OK  
5.  redis 127.0.0.1:6379> set age 10  
6.  QUEUED  
7.  redis 127.0.0.1:6379> set age 20  
8.  QUEUED  
9.  redis 127.0.0.1:6379> exec  
10. 1) OK  
11. 2) OK  
12. redis 127.0.0.1:6379> get age  
13. "20" 

        如何取消一个事务?

1.  redis 127.0.0.1:6379> get age  
2.  "20"  
3.  redis 127.0.0.1:6379> multi  
4.  OK  
5.  redis 127.0.0.1:6379> set age 30  
6.  QUEUED  
7.  redis 127.0.0.1:6379> set age 40  
8.  QUEUED  
9.  redis 127.0.0.1:6379> discard  
10. OK  
11. redis 127.0.0.1:6379> get age  
12. "20"

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

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

1.  redis 127.0.0.1:6379> incr name  
2.  (error) ERR value is not an integer or out of range  
3.  redis 127.0.0.1:6379> multi  
4.  OK  
5.  redis 127.0.0.1:6379> incr age  
6.  QUEUED  
7.  redis 127.0.0.1:6379> incr name  
8.  QUEUED  
9.  redis 127.0.0.1:6379> exec  
10. 1) (integer) 21  
11. 2) (error) ERR value is not an integer or out of range  
12. redis 127.0.0.1:6379> get age  
13. "21"  

        乐观锁复杂事务控制:

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

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

        1)第1步 session1

1.  redis 127.0.0.1:6379> get age  
2.  "10"  
3.  redis 127.0.0.1:6379> watch age  
4.  OK  
5.  redis 127.0.0.1:6379> multi  
6.  OK

        2)第2步 session2

1.  redis 127.0.0.1:6379> set age 30  
2.  OK  
3.  redis 127.0.0.1:6379> get age  
4.  "30" 

        3)第3步 session1

1.  redis 127.0.0.1:6379> set age 30  
2.  QUEUED  
3.  redis 127.0.0.1:6379> exec  
4.  (nil)  //因为有wathch age  
5.  redis 127.0.0.1:6379> get age  
6.  "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被修改就自动做快照。

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

2.  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

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

2.  #appendfsync always  //收到写命令就立即写入磁盘,最慢,但是保证完全的持久化  

3.  appendfsync everysec //每秒种写入磁盘一次,在性能和持久化方面做了很好的折中  

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

 

5.发布订阅消息

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

        1)第1步 session1

1.  redis 127.0.0.1:6379> subscribe tv1 tv2  
2.  Reading message... (press Ctrl+C to quit)  
3.  1) "subscribe"  
4.  2) "tv1"  
5.  3) (integer) 1  
6.  1) "subscribe"  
7.  2) "tv2"  
8.  3) (integer) 2 

        2)第2步 session2

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

        3)第3步 session3

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

        4)第4步 session1

1.  1) "message"  
2.  2) "tv1"  
3.  3) "test"  
4.  1) "message"  
5.  2) "tv2"  
6.  3) "haha"

        第4步 session2

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

 

6.虚拟内存的使用

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

        查了一下官方文档,发现虚拟内存其实一直是不建议使用的。在redis2.4版本以后,干脆就直接去掉了虚拟内存的支持,原因是虚拟内存可以使Redis在内存不够的情况下仍然可以将所有数据序列保存在内存里,这个过程很影响性能,会慢近10倍以上。感谢@卖红薯的提示。所以大家若想继续使用虚拟内存,则最低版本只能是redis2.4了。

        下面是vm相关配置:

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

1.  vm-enabled yes                  #开启vm功能  

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

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

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

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

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

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

1.  really-use-vm yes  

标签: redis
共有 人打赏支持
粉丝 187
博文 836
码字总数 521493
作品 5
评论 (4)
笔阁
之前写过一个东东,有空的可以配合着试试楼主的讲内容,在线可用。

http://www.hubwiz.com/course/55473be8ebfde9b5591bb813/
孟飞阳

引用来自“笔阁”的评论

之前写过一个东东,有空的可以配合着试试楼主的讲内容,在线可用。

http://www.hubwiz.com/course/55473be8ebfde9b5591bb813/
7979
卖红薯
虚拟内存可以使Redis在内存不够的情况下仍然可以将所有数据序列保存在内存里。
vm-enabled no

这个场景非常影响性能,官方新版本已经不支持。
孟飞阳

引用来自“卖红薯”的评论

虚拟内存可以使Redis在内存不够的情况下仍然可以将所有数据序列保存在内存里。
vm-enabled no

这个场景非常影响性能,官方新版本已经不支持。
多谢提示8181
×
孟飞阳
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: