redis常用命令2

1、STRING字符串

127.0.0.1:6379> ping
PONG
127.0.0.1:6379> set k1 v1   #设置值
OK
127.0.0.1:6379> get k1      #获得值
"v1"
127.0.0.1:6379> keys *     #获得所有key
1) "k1"
127.0.0.1:6379> exists k1   #判断某个key是否存在
(integer) 1   
127.0.0.1:6379> append k1 'liuxin'       #追加字符串,如果key不存在相当于新增key
(integer) 8
127.0.0.1:6379> get k1
"v1liuxin"
127.0.0.1:6379>strlen k1     #获取字符串长度
(integer)13
127.0.0.1:6379> append k1 'redis'
(integer) 13
127.0.0.1:6379> 
#i++
#步长i+=
127.0.0.1:6379> set views 0  #初始量为0
OK
127.0.0.1:6379> get views    #获取初始量
"0"
127.0.0.1:6379> incr views   #自增1
(integer) 1
127.0.0.1:6379> incr views   
(integer) 2
127.0.0.1:6379> decr views   #自减1
(integer) 1
127.0.0.1:6379> incrby views 10   #自增10,可以设置步长制定增量
(integer) 11
127.0.0.1:6379> decrby views 20   #自减20
(integer) -9
127.0.0.1:6379> get views
"-9"
#替换setrange
127.0
.0.1:6379> set key2 abcdefg OK 127.0.0.1:6379> get key2 "abcdefg" 127.0.0.1:6379> setrange key2 1 xx #替换指定位置开始的字符串 (integer) 7 127.0.0.1:6379> get key2 "axxdefg"
#字符串范围range
127.0.0.1:6379> set key 'hello word'    #设置key的值
OK
127.0.0.1:6379> get key
"hello word"
127.0.0.1:6379> getrange key 0 3      #截取字符串
"hell"
127.0.0.1:6379> getrange key 0 -1    #获取全部字符串
"hello word"
#setex(set with expire) #设置过期时间
#setnx(set if not exist) #不存在再设置(分布式锁中常用)
127.0
.0.1:6379> setex key3 30 kvalue #设置key3的值为kvalue 30秒过期 OK 127.0.0.1:6379> ttl key3 (integer) 21 127.0.0.1:6379> get key3 "kvalue" 127.0.0.1:6379> setnx mykey redis #如果mykey的值不存在,创建mykey (integer) 1 127.0.0.1:6379> keys * 1) "key2" 2) "mykey" 3) "key" 127.0.0.1:6379> ttl key3 (integer) -2 127.0.0.1:6379> setnx mykey 'mongodb' #如果mykey存在,创建失败 (integer) 0 127.0.0.1:6379> get mykey "redis"
#mset 批量设置
#mget 批量获取
127.0
.0.1:6379> mset k1 v1 k2 v2 k3 v3 #同时设置多个值 OK 127.0.0.1:6379> keys * 1) "k1" 2) "k3" 3) "k2"127.0.0.1:6379> mget k1 k2 k3 #同时获取多个值 1) "v1" 2) "v2" 3) "v3" 127.0.0.1:6379> msetnx k1 v1 k4 v4 #原子性操作,要么一起成功、要么一起失败 (integer) 0 127.0.0.1:6379> get k4 (nil)

#对象
set user:1{name:zhangsan,age:22} #设置一个user:1对象 值为Json字符来保存一个对象

  127.0.0.1:6379> set user:1 {name:zhangsan,age:22}
  OK
  127.0.0.1:6379> get user:1
  "{name:zhangsan,age:22}"
  127.0.0.1:6379> mset user:2:name lisi user:2:age 23
  OK
  127.0.0.1:6379> mget user:2:name user:2:age
  1) "lisi"
  2) "23"
  127.0.0.1:6379>

#getset 先get后set
127.0
.0.1:6379> getset db redis #如果不存在值则返回nil (nil) 127.0.0.1:6379> get db "redis" 127.0.0.1:6379> getset db mongodb #如果值存在,获取原来的值,并设置新的值 "redis" 127.0.0.1:6379> get db "mongodb" 127.0.0.1:6379>

 2、list命令:list命令都是以l开头,不区分大小写

127.0.0.1:6379> lpush list one  #将1个或多个值插入列表头部(左)
(integer) 1
127.0.0.1:6379> lpush list two
(integer) 2
127.0.0.1:6379> lpush list three
(integer) 3
127.0.0.1:6379> lrange list 0 1  #通过区间获取具体的值
1) "three"
2) "two"
127.0.0.1:6379> lrange list 0 -1  #获取list中的值
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> rpush list right  #将1个或多个值插入列表尾部(右)
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "right"
127.0.0.1:6379> 
#lpop 移除最左边元素
#rpop 移除最右边元素
127.0
.0.1:6379> LRANGE list 0 -1 1) "three" 2) "two" 3) "one" 4) "right" 127.0.0.1:6379> lpop list "three" 127.0.0.1:6379> rpop list "right" 127.0.0.1:6379> lrange list 0 -1 1) "two" 2) "one" 127.0.0.1:6379>
#lindex通过下标获取值
127.0
.0.1:6379> lrange list 0 -1 1) "two" 2) "one" 127.0.0.1:6379> lindex list 0 #通过下标获取List某一个值 "two" 127.0.0.1:6379> lindex list 1 "one" 127.0.0.1:6379>
#llen获取list长度
127.0
.0.1:6379> lpush list one (integer) 1 127.0.0.1:6379> lpush list two (integer) 2 127.0.0.1:6379> lpush list three (integer) 3 127.0.0.1:6379> llen list #返回列表长度 (integer) 3 127.0.0.1:6379>
#lrem移除指定的值
127.0
.0.1:6379> lpush list three (integer) 4 127.0.0.1:6379> lrange list 0 -1 1) "three" 2) "three" 3) "two" 4) "one" 127.0.0.1:6379> lrem list 1 one #移除list集合中指定个数的value,精确匹配(移除1个,值为one) (integer) 1 127.0.0.1:6379> lrange list 0 -1 1) "three" 2) "three" 3) "two" 127.0.0.1:6379> lrem list 1 three (integer) 1 127.0.0.1:6379> lrange list 0 -1 1) "three" 2) "two" 127.0.0.1:6379> lpush list three (integer) 3 127.0.0.1:6379> lrange list 0 -1 1) "three" 2) "three" 3) "two" 127.0.0.1:6379> lrem list 2 three #移除list 集合中2个three (integer) 2 127.0.0.1:6379> lrange list 0 -1 1) "two" 127.0.0.1:6379>
#ltrim截取字符
127.0
.0.1:6379> lpush mylist hello (integer) 1 127.0.0.1:6379> lpush mylist hello1 (integer) 2 127.0.0.1:6379> lpush mylist hello2 (integer) 3 127.0.0.1:6379> lpush mylist hello3 (integer) 4 127.0.0.1:6379> lrange list 0 -1 (empty array) 127.0.0.1:6379> lrange mylist 0 -1 1) "hello3" 2) "hello2" 3) "hello1" 4) "hello" 127.0.0.1:6379> ltrim mylist 1 2 #通过下标截取指定位置开始指定长度的字符,这个list已经改变,只剩下截取到的元素 OK 127.0.0.1:6379> lrange mylist 0 -1 1) "hello2" 2) "hello1" 127.0.0.1:6379>
#rpoplpush 移除列表最后一个元素,将其添加到新的列表中
127.0
.0.1:6379> rpush mylist hello (integer) 1 127.0.0.1:6379> rpush mylist hello1 (integer) 2 127.0.0.1:6379> lpush mylist hello2 (integer) 3 127.0.0.1:6379> lrange mylist 0 -1 1) "hello2" 2) "hello" 3) "hello1" 127.0.0.1:6379> rpoplpush mylist myotherlist #移除最后一个元素hello1,将其添加到新的列表中 "hello1" 127.0.0.1:6379> lrange mylist 0 -1 1) "hello2" 2) "hello" 127.0.0.1:6379> lrange myotherlist 0 -1 # 1) "hello1" 127.0.0.1:6379>
#lset 将列表中指定下标的值替换为另一个值,更新操作
127.0
.0.1:6379> exists list #判断这个列表是否存在 (integer) 0 127.0.0.1:6379> lset list 0 item (error) ERR no such key #如果不存在我们去更新就会报错 127.0.0.1:6379> lpush list value (integer) 1 127.0.0.1:6379> lrange list 0 0 1) "value" 127.0.0.1:6379> lset list 0 item #如果存在就更新当下列表的值 OK 127.0.0.1:6379> lrange list 0 0 1) "item" 127.0.0.1:6379> lset list 1 other #如果不存在,则会报错 (error) ERR index out of range 127.0.0.1:6379>
#linsert 插入命令
127.0
.0.1:6379> rpush mylist hello (integer) 1 127.0.0.1:6379> rpush mylist word (integer) 2 127.0.0.1:6379> linsert mylist after 'word' 'other' #在word之后插入 (integer) 3 127.0.0.1:6379> lrange mylist 0 -1 1) "hello" 2) "word" 3) "other" 127.0.0.1:6379> linsert mylist before 'hello' 'new' #在hello之前插入 (integer) 4 127.0.0.1:6379> lrange mylist 0 -1 1) "new" 2) "hello" 3) "word" 4) "other" 127.0.0.1:6379>
3、set
#随机删除key
127.0
.0.1:6379> smembers myset 1) "xiaomin" 2) "nihao" 127.0.0.1:6379> sopo myset (error) ERR unknown command `sopo`, with args beginning with: `myset`, 127.0.0.1:6379> spop myset #随机删除一些set集合中的元素 "nihao" 127.0.0.1:6379> smembers myset 1) "xiaomin" 127.0.0.1:6379>
#移动元素到指定位置
127.0
.0.1:6379> sadd myset liu (integer) 1 127.0.0.1:6379> sadd myset xin (integer) 1 127.0.0.1:6379> sadd myset nihao (integer) 1 127.0.0.1:6379> sadd myset2 hello (integer) 1 127.0.0.1:6379> smembers myset 1) "nihao" 2) "liu" 3) "xin" 127.0.0.1:6379> smembers myset2 1) "hello" 127.0.0.1:6379> smove myset myset2 liu #将一个指定元素移动到另一个集合 (integer) 1 127.0.0.1:6379> smembers myset 1) "nihao" 2) "xin" 127.0.0.1:6379> smembers myset2 1) "liu" 2) "hello" 127.0.0.1:6379>

 4、bitmap

 5、事务

redis事务本质:一组命令的集合,一个事务中所有命令都会被序列化,在事务执行过程中,会按照顺序执行。

一次性、顺序性、排他性,执行一系列的命令。

-----set  set  set ...----

Redis事务没有隔离级别的概念!

所有的命令在事务中并没有直接被执行,只有在发起执行命令的时候才会执行!exec

Redis单条命令是有原子性的,但事务不保证原子性!

redis的事务:

  • 开启事务(multi)
  • 命令入队()
  • 执行事务(exec)  
127.0.0.1:6379> clear
127.0.0.1:6379> multi    #开启事务
OK
#命令入队
127.0.0.1:6379(TX)> set k1 v1 QUEUED 127.0.0.1:6379(TX)> set k2 v2 QUEUED 127.0.0.1:6379(TX)> get k2 QUEUED 127.0.0.1:6379(TX)> set k3 v3 QUEUED 127.0.0.1:6379(TX)> exec #执行事务 1) OK 2) OK 3) "v2" 4) OK 127.0.0.1:6379>
#放弃事务
127.0
.0.1:6379> multi #开启事务 OK 127.0.0.1:6379(TX)> set k1 v1 QUEUED 127.0.0.1:6379(TX)> set k2 v2 QUEUED 127.0.0.1:6379(TX)> set k4 v4 QUEUED 127.0.0.1:6379(TX)> DISCARD #取消事务 OK 127.0.0.1:6379> get k4 #事务队列中的命令都不会被执行 (nil) 127.0.0.1:6379>

redis事务执行时常见的有2种错误

①编译型异常(代码有异常,命令有错),事务中所有命令都不会被执行

127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> getset k3  #命令出错
(error) ERR wrong number of arguments for 'getset' command
127.0.0.1:6379(TX)> set k4 v4
QUEUED
127.0.0.1:6379(TX)> set k5 v5
QUEUED
127.0.0.1:6379(TX)> exec  #执行事务出错
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get k5
(nil)
127.0.0.1:6379> get k4  #所有命令都不会被执行
(nil)
127.0.0.1:6379> 

②运行时异常(1/0),如果事务队列中存在语法性,那么执行命令的时候,其他命令是可以正常执行的,错误命令抛出异常

127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> incr k1  #执行时候失败
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> get k3
QUEUED
127.0.0.1:6379(TX)> exec
1) (error) ERR value is not an integer or out of range  #虽然第一条命令出错,但是依旧正常执行成功了
2) OK
3) OK
4) "v3"
127.0.0.1:6379> get k2
"v2"
127.0.0.1:6379> get k3
"v3"
127.0.0.1:6379> 

6、监控 watch

  • 悲观锁:很悲观,认为什么时候都会出问题,无论做什么都会加锁!
  • 乐观锁
  1. 很乐观、认为什么时候都不会出现问题,所以不会上锁!更新数据时候去判断一下,在此期间是否有人修改数据。
  2. 获取version
  3. 更新时候比较version
#redis监视测试
127.0
.0.1:6379> set money 100 OK 127.0.0.1:6379> set out 0 OK 127.0.0.1:6379> watch money #监视money对象 OK 127.0.0.1:6379> multi #事务正常结束,期间数据没有变动,这个时候正常执行成功 OK 127.0.0.1:6379(TX)> decrby money 20 QUEUED 127.0.0.1:6379(TX)> incrby out 20 QUEUED 127.0.0.1:6379(TX)> exec 1) (integer) 80 2) (integer) 20 127.0.0.1:6379>
#测试多线程修改值,使用watch可以当作redis的乐观锁操作
127.0
.0.1:6379> set money 100 OK 127.0.0.1:6379> set out 10 OK 127.0.0.1:6379> watch money #监视money OK 127.0.0.1:6379> multi OK 127.0.0.1:6379(TX)> decrby money 10 QUEUED 127.0.0.1:6379(TX)> incrby money 10 QUEUED 127.0.0.1:6379(TX)> exec #执行事务前,另外一个线程修改了我们的值,这个时候就会导致事务执行失败 (nil) 127.0.0.1:6379>
127.0.0.1:6379> unwatch  #①获取失败后,先解锁
OK127.0.0.1:6379> watch money #②再获取最新的值,再次监视
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> decrby money 10
QUEUED
127.0.0.1:6379(TX)> incrby out 10
QUEUED
127.0.0.1:6379(TX)> exec  #③比对监视的值是否发生变化,如果没有变化,可以执行成功,否则执行失败
1) (integer) 990
2) (integer) 20
127.0.0.1:6379> 

 7、RDB

 8、AOF(Append only file)

将所有的命令记录下来,恢复的时候把这些命令全部执行一遍。默认是不开启的,需要进行手动配置,只需要将appendonly 改为yes就开启了aof,重启redis就可以生效。如果这个aof有错误,这时候redis是启动不起来的,我们需要修复aof文件。如果aof文件大于64兆,会fork一个新的进程来将我们的文件重写。

优缺点:

 

 

 9、发布订阅

Redis发布订阅是一种消息通信模式:发布者(pub)发送消息,订阅者(sub)接收消息。微信、微博、订阅。redis客户端可以订阅任意数量的频道。

  

 订阅端:

127.0.0.1:6379> subscribe kuangshengshuo  #订阅kuangshengshuo频道
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "kuangshengshuo"
3) (integer) 1
#等待接收推送的消息
1) "message"  #消息
2) "kuangshengshuo"  #频道
3) "nihao"  #消息内容

1) "message"
2) "kuangshengshuo"
3) "word"

发送端:

127.0.0.1:6379> publish kuangshengshuo nihao  #发布者发布消息到频道
(integer) 1
127.0.0.1:6379> publish kuangshengshuo word  #发布者发布消息到订阅频道
(integer) 1
127.0.0.1:6379> 

  

10、主从复制

 

 

 

 

 

 

 主从复制、读写分离,80%情况下是进行读操作,最低配置是一主二从。

 环境配置:

127.0.0.1:6379> info replication   #查看当前库的信息
# Replication
role:master  #角色
connected_slaves:0   #没有从机
master_failover_state:no-failover
master_replid:d6602c86062dca18863ae603704b1949c8e6219e
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6379> 

修改配置:

①端口 ②pid名字 ③log文件名字 ④dump.rdb名字

配置完成后启动服务,默认情况下每台服务器都是主节点,一般情况下只配置从机

 

 

 一主(79)二从(80,81)

#6380从机信息
127.0
.0.1:6380> slaveof 127.0.0.1 6379 #6380端口服务器认6379为主机 OK 127.0.0.1:6380> info replication # Replication role:slave #当前角色 master_host:127.0.0.1 #主机信息 master_port:6379 master_link_status:up master_last_io_seconds_ago:7 master_sync_in_progress:0 slave_read_repl_offset:14 slave_repl_offset:14 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:2f8e64512dfcbfb79eb4a3b2c23a35e602869c5c master_replid2:0000000000000000000000000000000000000000 master_repl_offset:14 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:14 127.0.0.1:6380>
#6379主机信息
127.0
.0.1:6379> info replication # Replication role:master connected_slaves:1 #从机配置 slave0:ip=127.0.0.1,port=6380,state=online,offset=182,lag=1 #从机信息 master_failover_state:no-failover master_replid:2f8e64512dfcbfb79eb4a3b2c23a35e602869c5c master_replid2:0000000000000000000000000000000000000000 master_repl_offset:182 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:182 127.0.0.1:6379>

主机可以写,从机只能读,主机的信息和数据会自动被从机保存。

127.0.0.1:6379> set k1 v1  #主机可以写
OK
127.0.0.1:6379> keys *
1) "k1"
127.0.0.1:6379> 
(empty array)
127.0.0.1:6380> clear
127.0.0.1:6380> get k1
"v1"
127.0.0.1:6380> set k2 v2  #从机不能写
(error) READONLY You can't write against a read only replica.
127.0.0.1:6380> 

测试:主机断开连接,从机依旧连接到主机,但是没有写操作,这个时候如果主机回来,从机依旧可以直接获取到主机写的信息。

如果是使用命令行配置的主从,从机如果重启就会变回主机,只要变回从机就会立马从主机中获取数据。

 

 

 配置方式二:层层链路:上一个主节点连接下一个从节点

 

 

 

 11、哨兵模式

 

 

 

我们目前状态是一主二从:

1、配置哨兵文件sentinel.conf

#sentinel monitor 被监控的名称 Host port 1   #数字1代表当主机挂了,从机投票让谁接替成为主机,票数最多的就会成为主机
sentinel monitor myredis 127.0.0.1 6379 1

2、启动哨兵

[root@izm5egx7lv78u7ac9pk8ckz bin]# redis-sentinel kconfig/sentinel.conf  #启动哨兵
28440:X 16 Nov 2021 17:00:22.392 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
28440:X 16 Nov 2021 17:00:22.392 # Redis version=6.2.6, bits=64, commit=00000000, modified=0, pid=28440, just started
28440:X 16 Nov 2021 17:00:22.392 # Configuration loaded
28440:X 16 Nov 2021 17:00:22.393 * monotonic clock: POSIX clock_gettime
                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 6.2.6 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                  
 (    '      ,       .-`  | `,    )     Running in sentinel mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 26379
 |    `-._   `._    /     _.-'    |     PID: 28440
  `-._    `-._  `-./  _.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |           https://redis.io       
  `-._    `-._`-.__.-'_.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'                                               

28440:X 16 Nov 2021 17:00:22.393 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
28440:X 16 Nov 2021 17:00:22.396 # Sentinel ID is 580c7dc3ba77902a1ae27007ecd50f38e8ba1c98
28440:X 16 Nov 2021 17:00:22.396 # +monitor master myredis 127.0.0.1 6379 quorum 1
28440:X 16 Nov 2021 17:00:22.397 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ myredis 127.0.0.1 6379
28440:X 16 Nov 2021 17:00:22.400 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ myredis 127.0.0.1 6379

 如果主机宕机:master节点断开,这时候会从从机随机选择一个服务器(这里面有一个投票算法)。

12、缓存穿透

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2021-11-02 12:02  S流星  阅读(91)  评论(0编辑  收藏  举报