redis使用

from my typora

redis 使用

redis基本命令

一个redis实例可以包括多个数据库,客户端可以指定连接某个redis实例的哪个数据库,就好比一个mysql中创建多个数据库,客户端连接时指定连接哪个数据库。

一个redis实例最多可以提供16个数据库,下标从0到15,客户端默认连接0号数据库,也可以通过select选择连接哪个数据库,如下连接1号库:

lsnu@lsnu-Aspire-AG1731:/usr/local/redis$ ./bin/redis-cli
127.0.0.1:6379> keys *
(empty list or set)
# select 同mysql中的use
127.0.0.1:6379> select 0
OK
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> select 15
OK
127.0.0.1:6379[15]> keys *
(empty list or set)
127.0.0.1:6379[15]> select 16
(error) ERR DB index is out of range
# 退出和mysql相同:exit或者quit

set [key]:设置一个键值对

$ set name mzy

get [key]:查看键值对:name

$ get name

del [key]:删除键值对:name

$ del name

keys *:查看当前数据库中的键值对(默认是0号库)

# 查看所有
$ keys *

clear:清屏

$ clear

select [0-15]:从默认的0号库改变到1号库

127.0.0.1:6379> select 1
OK

move [key] 0-15:将0号库中的name,移动到1号库中

# 定位到0号库
$ select 0
# 移动到一号库
$ move name 1
# 查看当前0号库中是否存在name
$ keys * / get name
(empty list or set) / (nil)
# 切换到1号库中,查看是否存在
$ select 1
$ keys * / get name
1) "name" / "mzy"

存放中文

127.0.0.1:6379> set name 哈哈哈
OK
127.0.0.1:6379> get name
"xe5x93x88xe5x93x88xe5x93x88"

echo:redis中也可以使用echo命令,但是我认为没什么用;

$ echo hhha
hhha

quit或exit:退出连接

quit / exit # 都可以

dbsize:返回当前数据库中key的数目

$ dbsize
127.0.0.1:6379> dbsize
(integer) 2

info:获取服务器的信息和统计

$ info
# Server
... 
# Clients
... 
# Memory
... 
# Persistence
... 
# Stats
... 
# Replication
... 
# CPU
... 
# Cluster
... 
# Keyspace
... 

flushdb:删除当前选择数据库中的所有key:

$ flushdb

flushall:删除所有数据库的所有key:

$ flushall

redis做消息订阅与发布

redis所特有的,消息发布订阅:

开启三个redis客户端窗口:

在第一个连接中,订阅mychat频道。此时如果没有人“发布”消息,当前窗口处于等待状态。

127.0.0.1:6379> subscribe mychat
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "mychat"
3) (integer) 1

在第二个窗口,向mychat窗口发布(publish)消息:

127.0.0.1:6379> publish mychat '111'
(integer) 1

发现第一个窗口马上显示出了’111’

Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "mychat"
3) (integer) 1
1) "message"
2) "mychat"
3) "111"

在第三个窗口中使用psubcribe,订阅多个频道:

# 订阅所有以my* 开头的消息
127.0.0.1:6379> psubscribe my*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "my*"
3) (integer) 1

在第二个窗口中分别向mychat和mychat2发布消息:

127.0.0.1:6379> publish mychat '111'
(integer) 1
127.0.0.1:6379> publish mychat '222'
(integer) 2
127.0.0.1:6379> publish mychat '333'
(integer) 2
127.0.0.1:6379> publish mychat2 '333'
(integer) 1
127.0.0.1:6379> 

发现窗口1:

127.0.0.1:6379> subscribe mychat
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "mychat"
3) (integer) 1
1) "message"
2) "mychat"
3) "111"
1) "message"
2) "mychat"
3) "222"
1) "message"
2) "mychat"
3) "333"

发现窗口3:

127.0.0.1:6379> psubscribe my*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "my*"
3) (integer) 1
1) "pmessage"
2) "my*"
3) "mychat"
4) "222"
1) "pmessage"
2) "my*"
3) "mychat"
4) "333"
1) "pmessage"
2) "my*"
3) "mychat2"
4) "333"

只有窗口3收到了mychat2。

redis事务

和众多数据库一样,redis作为NoSQL数据库同样也提供了事务机制。

redis中的事务,通过MULTI/EXEC/DISCARD这三个命令实现事务。

1.在redis中,事务直接被设置为最高级别,所有命令都会被串行化的顺序执行,事务执行期间,redis不会再为其它任何客户端请求提供任何服务,从而保证了事务中的所有命令被原子的执行。

不要看redis是串行执行的,看起来好像很慢,其实不是,redis直接操作的内存,其实速度已经很快了;如果你设置它能为多个客户端同时提供服务,不通过串行的方式的话,我觉得反而是影响了redis的性能,因为这样来回切,进行隔离,反而降低了redis的执行速度!

同时补充:如果现在你要从D盘复制两个文件(文件A、文件B)到E盘中,你会同时复制还是一个个复制?

按照我们的惯性思维应该是同时复制,但是其实这样反而会更慢一些的,因为底层CPU要来回切换,一会儿复制一下文件A,一会儿复制一下文件B。切换反而更耗性能;由此说到了多线程编程,我认为大多数场景下多线程编程其实是不优的,除了一些特定的业务和逻辑场景,在我看来多线程编程大多数情况下很鸡肋。

2.和关系型的数据中的事务相比,在redis事务中如果有某一条命令执行失败,其后命令仍然会被继续执行。

而相比在我们的关系型数据库中,如果出现了事务异常,则会直接结束,不会往后执行了,并开始进行回滚。

3.redis事务的流程:通过MULTI命令开启事务(同关系型数据库中的begin transaction),该命令执行之后,执行所有命令都被视为事务之内的操作,最后通过执行EXEC(提交)/DISCARD(回滚)来批量处理该事务之内的所有操作!

multi:开启事务相当于关系型数据库中的begin transaction;

exec:相当于关系型数据库中的commit;

discard:相当于关系型数据库中的rollback;

4.在事务开启之前如果出现通讯故障网络中断,其后所有待执行的语句都不会被服务器执行。然而如果网络中断发生在客户端执行EXEC命令之后,那么该事务中的所有命令都会被服务器执行。

5、当使用Append-0Only模式时,Redis会通过调用系统函数write将该事务内的所有写操作在本次调用中全部写入磁盘。然而如果在写入的过程中出现系统崩溃,I如电源故障导致的宕机,那么此时也许只有部分数据被写入到磁盘,而另外一部分数据却已经丢失。Redis 服务器会在重新启动时执行一系列必要的一致性检测,一旦发现类似问题,就会立即退出并给出相应的错误提示。此时,我们就要充分利用Redis工具包中提供的redis- check-aof工具,该工具可以帮助我们定位到数据不一.致的错误,并将已经写入的部分数据进行回滚。修复之后我们就可以再次重新启动Redis服务器了。

测试事务

前:

​ incr,对一个数字进行增长,类似++:incr num 相当于 num++

​ incrby num 5,类似于num += 5:incr num 相当于 num = num + 5

测试redis连通性:

步骤1:在窗口1设置num,并获得数据

127.0.0.1:6379> set num 1
OK
127.0.0.1:6379> get num 
"1"

步骤2:在窗口2,num累加1,并获得数据

127.0.0.1:6379> get num
"1"
127.0.0.1:6379> incr num
(integer) 2
127.0.0.1:6379> get num
"2"

步骤3:在窗口1,获得数据

127.0.0.1:6379> set num 1
OK
127.0.0.1:6379> get num 
"1"
127.0.0.1:6379> get num
"2"
# 发现已经受到影响

步骤4:在窗口1,开启事务,多次累加数据

127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr num
QUEUED # 在排队中...
127.0.0.1:6379> incr num
QUEUED

步骤5:在窗口2获得数据

# 发现此刻数据并没有变化
127.0.0.1:6379> get num
"2"

步骤6:在窗口1提交事务exec

127.0.0.1:6379> exec
1) (integer) 3
2) (integer) 4

步骤7:在窗口2查询num

# 发现事务已经提交了
127.0.0.1:6379> get num
"4"

步骤8:在窗口1再次累加(不开启事务)

127.0.0.1:6379> incr num
(integer) 5
127.0.0.1:6379> incr num
(integer) 6

步骤9:窗口2查询

# 受到影响
127.0.0.1:6379> get num
"6"

步骤10:窗口1开启事务累加两次,然后discard。

127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr num
QUEUED
127.0.0.1:6379> incr num
QUEUED
127.0.0.1:6379> discard
OK

步骤11:窗口2再次查询num

# 发现事务没有提交了
127.0.0.1:6379> get num
"6"

失败测试(测试和关系型数据库不一样的地方:在redis事务中如果有某一条命令执行失败,其后命令仍然会被继续执行。)

# 首先把num清0,避免造成误导
127.0.0.1:6379> set num 0
OK
# 开启事务
127.0.0.1:6379> multi 
OK
# 增加5
127.0.0.1:6379> incrby num 5
QUEUED
# 不可识别的x,造成异常
127.0.0.1:6379> incrby num x
QUEUED
# 增加5
127.0.0.1:6379> incrby num 5
QUEUED
# 提交执行事务
127.0.0.1:6379> exec
1) (integer) 5
2) (error) ERR value is not an integer or out of range
3) (integer) 10
127.0.0.1:6379> get num
"10"
# 补:最后有人可能会想,如果我设置一个key为x,给一个数字的值,例如:5
# 那redis,会不会引用呢?答案是不会,至少在incrby 中不会,已测试!

补充:

以上:

​ multi必须和exec或者discard成对出现,不然会出现:(error) ERR MULTI calls can not be nested

redis的持久化

redis持久化支持两种方式:RDB和AOF;可以二者单独使用,也可以将二者结合使用。

RDB

快照:snapshots(比较节省空间,很快),记录当前在内存中的状态(只用记当前,不管过程)。

RDB的优势:

持久化只有一个文件,易于备份;并且因为是快照,只存数据的缘故,启动比AOF更快(数据量较大的情况下)。

在redis的根目录下,发现多了一个dump.rdb,就是redis持久化存储的数据(RDB方式下的)

lsnu@lsnu-Aspire-AG1731:/usr/local/redis$ ll
总用量 80
drwxr-xr-x  3 root root  4096 11月 10 16:29 ./
drwxr-xr-x 11 root root  4096 11月  9 18:02 ../
drwxr-xr-x  2 root root  4096 11月  9 18:06 bin/
-rw-r--r--  1 root root   151 11月 10 16:29 dump.rdb
-rw-r--r--  1 root root 62156 11月  9 18:23 redis.conf

所以归档就很容易了:直接备份dump.rdb这一个文件就好了!

RDB的劣势:

数据的高可用性无法保证,系统宕机的话,会造成数据丢失。

RDB采用fork子进程协助完成持久化,一旦数据量大了,可能造成服务器停止服务0-1000ms的情况。

RDB快照参数设置:
# 在redis.conf 中配置
save 900 1     # 每900秒,15分钟(如果有1个key发生变化),则dump内存快照。
save 300 10    # 每300秒,5分钟(如果有10个key发生变化),则dump内存快照。
save 60  10000 # 每60秒,1分钟(如果有10000个key发生变化),则dump内存快照。

AOF

以日志的方式记录,(记录了过程,做了什么,记下命令,记录修改、删除或者增加的操作;但是查询忽略了)

只要更改了redis,就记录下这些命令;原理就是,每次启动redis,把从最初开始执行过的所有:增、删、改命令全部执行一遍来恢复到当前状态。

AOF的劣势

1.相同数量的数据集,AOF文件通常大于RDB文件

2.同步的策略不同,导致AOF在运行上效率慢于RDB。

AOF的配置
always # 每次有数据修改都会写入AOF文件
everysec # 每秒钟同步一次,该策略为AOF的缺省策略
no # 从不同步。高效但是不会持久化。
# 默认是关闭的
appendonly no -> appendonly yes

# appendfsync always
appendfsync everysec
# appendfsync no

无持久化

就做缓存,不持久化。

原文地址:https://www.cnblogs.com/mzywucai/p/11053335.html