redis

为什么使用nosql(not only sql)

  1. 单机mysql时期
    1. jsp到dao到数据库在这里插入图片描述
  2. Memcached(缓存)+Mysql+垂直拆分
    1. jsp到dao到Memcached到多个数据库实例在这里插入图片描述
  3. Mysql的主从读写分离
    1. jsp到dao到Memcached在这里插入图片描述
      1. Memcached到主数据库负责写(增删改)数据,从库在主库写完之后立刻更新数据;
      2. Memcached到从数据库负责读(查)数据;
  4. 分库分表+水平拆分+mysql集群
    1. jsp到dao到Memcached到一个个集群,集群中对应读写分离在这里插入图片描述
  5. Mysql的扩展性瓶颈
    1. 如果需要存储很大空间的文件,Mysql扩展性差,大数据io差,表结构更改困难;在这里插入图片描述
  6. 现状
    在这里插入图片描述

安装

  1. 下载redis压缩包
    1. 使用wget命令后接资源地址下载压缩包
    2. wget http://download.redis.io/releases/redis-4.0.8.tar.gz
    3. 也可以使用vmware的共享目录在windows上面下载然后放进linux中
  2. 将压缩包放进/opt目录
    1.使用tar -zxvf redis-3.0.4.tar.gz解压
    2.然后在解压目录中使用make命令
    3.如果make命令报缺少gcc则使用yum命令安装 yum install gcc-c++
    4.make install

启动redis

  1. 备份redis.conf文件到/myredis文件夹中,然后将备份的redis.conf(下面的都是用的备份)中的daemonize no改成yes;
  2. 然后在/usr/local/bin下面使用redis-server /myredis/redis.conf启动服务器,然后redis-cli -p 6379启动客户端,然后ping执行连通性测试,正确输出pong,那么就正常启动了;
  3. 退出输出shutdown然后exit即可;

几个常用命令

  1. redis有16个库,可以使用select 数字来选择库
  2. 使用dbsize可以查看当前库中有多少个键值对
  3. 使用flushdb可以清空当前库
  4. 使用flushall可以清空所有库

redis数据类型

每种类型对应的底层结构:https://www.cnblogs.com/charlas/p/7606077.html

  1. 字符对象:int,raw,embstr
  2. 列表对象:ziplist,skiplist
  3. hash对象:ziplist,hashtable
  4. set对象:intset,hashtable
  5. zset:ziplist,skiplist

key(键)

使用

  1. keys *:查询当前库的所有key
127.0.0.1:6379> keys *
1) "k2"
2) "k3"
3) "k1"
  1. exists key:判断key是否存在,存在返回1,不存在返回0;
127.0.0.1:6379> EXISTS k1
(integer) 1
127.0.0.1:6379> EXISTS k11
(integer) 0
  1. move key db:将key从当前库移动到db库;
127.0.0.1:6379> keys *
1) "k2"
2) "k3"
3) "k1"
127.0.0.1:6379> move k1 1
(integer) 1
127.0.0.1:6379> keys *
1) "k2"
2) "k3"
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> keys *
1) "k1"
127.0.0.1:6379[1]> 
  1. expire key time:将key设置成time(秒)过期
  2. ttl key:查看key的生命周期,-1表示永不过期,-2表示已过期(移除该元素),一般配合expire命令使用
127.0.0.1:6379> keys * 
1) "k2"
2) "k3"
3) "k1"
127.0.0.1:6379> ttl k1
(integer) -1
127.0.0.1:6379> expire k1 10
(integer) 1
127.0.0.1:6379> ttl k1
(integer) 8
127.0.0.1:6379> ttl k1
(integer) 6
127.0.0.1:6379> ttl k1
(integer) 5
127.0.0.1:6379> ttl k1
(integer) 4
127.0.0.1:6379> ttl k1
(integer) 4
127.0.0.1:6379> ttl k1
(integer) 3
127.0.0.1:6379> ttl k1
(integer) 2
127.0.0.1:6379> ttl k1
(integer) 1
127.0.0.1:6379> ttl k1
(integer) 1
127.0.0.1:6379> ttl k1
(integer) -2
127.0.0.1:6379> get k1
(nil)
127.0.0.1:6379> keys *
1) "k2"
2) "k3"
127.0.0.1:6379> 
  1. type key :查看key是什么类型
127.0.0.1:6379> type k2
string
127.0.0.1:6379> LPUSH mylist 1 2 3 4 5
(integer) 5
127.0.0.1:6379> LRANGE mylist 0 -1
1) "5"
2) "4"
3) "3"
4) "2"
5) "1"
127.0.0.1:6379> type mylist
list
127.0.0.1:6379> 
  1. del key:表示删掉key
127.0.0.1:6379> del mylist
(integer) 1
127.0.0.1:6379> keys *
1) "k2"
2) "k3"
127.0.0.1:6379> 
  1. persist key:移除key的有效时间,key将保持永久
127.0.0.1:6379> keys *
1) "k2"
2) "k3"
127.0.0.1:6379> expire k2 60
(integer) 1
127.0.0.1:6379> ttl k2
(integer) 56
127.0.0.1:6379> PERSIST k2
(integer) 1
127.0.0.1:6379> ttl k2
(integer) -1
127.0.0.1:6379> 
  1. randomkey :从已有的所有key中随机返回一个key
1) "k2"
2) "k3"
127.0.0.1:6379> RANDOMKEY
"k2"
127.0.0.1:6379> 
  1. rename key newkey:修改key的名称为newkey
127.0.0.1:6379> keys *
1) "k2"
2) "k3"
127.0.0.1:6379> RENAME k2 k1
OK
127.0.0.1:6379> keys *
1) "k1"
2) "k3"
127.0.0.1:6379> 

String(字符串)

  1. String是redis最基本的类型,可以理解成跟Memcached一模一样的类型,一个key对应一个value
  2. string类型是二进制安全的,意思是redis的string可以包含任何数据,比如jpg图片或者序列化对象;
  3. string类型是redis的最基本的数据类型,一个redis中字符串value最多可以是512M

使用

  1. set key value:设置key的值为value
127.0.0.1:6379> keys *
1) "k1"
2) "k3"
127.0.0.1:6379> set k2 v2
OK
  1. get key:获取key的值
127.0.0.1:6379> keys *
1) "k2"
2) "k1"
3) "k3"
127.0.0.1:6379> get k1
"v1"
  1. del key :表示删除key
127.0.0.1:6379> keys *
1) "k2"
2) "k1"
3) "k3"
127.0.0.1:6379> del k1
(integer) 1
127.0.0.1:6379> keys *
1) "k2"
2) "k3"
  1. append key newvalue:表示在key的原value值拼接加上newvalue
  2. strlen key :表示key的长度
127.0.0.1:6379> keys *
1) "k2"
2) "k3"
127.0.0.1:6379> get k2
"v2"
127.0.0.1:6379> STRLEN k2
(integer) 2
127.0.0.1:6379> APPEND k2 12345
(integer) 7
127.0.0.1:6379> strlen k2
(integer) 7
127.0.0.1:6379> get k2
"v212345"
  1. incr key :将key值加一(key只能是数字,以下三种命令相同)
  2. decr key:将key值减一
  3. incrby key num:将key的值加num
  4. decrby key num:将key的值减num
127.0.0.1:6379> get k2
"1"
127.0.0.1:6379> INCR k2
(integer) 2
127.0.0.1:6379> get k2
"2"
127.0.0.1:6379> DECR k2
(integer) 1
127.0.0.1:6379> get k2
"1"
127.0.0.1:6379> INCRBY k2 3
(integer) 4
127.0.0.1:6379> get k2
"4"
127.0.0.1:6379> DECRBY k2 3
(integer) 1
127.0.0.1:6379> get k2
"1"
  1. getrange key n m:获取key从下标n到m(不包含)的子字符串
127.0.0.1:6379> get k2
"v212345"
127.0.0.1:6379> GETRANGE k2 0 -1
"v212345"
127.0.0.1:6379> GETRANGE k2 0 3
"v212"
  1. setrange key n newvalue :从key的第n(包含)位开始覆盖newvalue,若key不存在会新建key
127.0.0.1:6379> keys *
1) "k2"
2) "k3"
127.0.0.1:6379> SETRANGE k1 0 XXX
(integer) 3
127.0.0.1:6379> keys *
1) "k2"
2) "k1"
3) "k3"
127.0.0.1:6379> get k1
"XXX"
127.0.0.1:6379> get k2
"v212345"
127.0.0.1:6379> SETRANGE k2 0 XXX
(integer) 7
127.0.0.1:6379> get k2
"XXX2345"
  1. setex(set with expire) key time value:设置key值为value并设置过期时间time秒
127.0.0.1:6379> setex k3 10 v4
OK
127.0.0.1:6379> ttl k3
(integer) 8
127.0.0.1:6379> get k3
"v4"
127.0.0.1:6379> ttl k3
(integer) 1
127.0.0.1:6379> ttl k3
(integer) -2
127.0.0.1:6379> get k3
(nil)
  1. setnx(set if not exist) key value:设置key的值为value当key不存在时才设置,存在不覆盖
127.0.0.1:6379> keys *
1) "k2"
2) "k1"
127.0.0.1:6379> get k1
"XXX"
127.0.0.1:6379> setnx k1 123123
(integer) 0
127.0.0.1:6379> get k1
"XXX"
127.0.0.1:6379> setnx k3 123123
(integer) 1
127.0.0.1:6379> get k3
"123123"
  1. mset key1 value1 key2 value2…:设置多个值(more)
  2. mget key1 key2 key3 …:获取多个值
  3. msetnx key1 value1…:设置多个值,当有任意一个key存在则所有的key都设置失败
127.0.0.1:6379> keys *
1) "k2"
2) "k1"
3) "k3"
4) "k4"
127.0.0.1:6379> msetnx k4 v44 k5 v55
(integer) 0
127.0.0.1:6379> mget k4 k5
1) "v4"
2) (nil)
127.0.0.1:6379> msetnx k5 v55 k6 v66
(integer) 1
127.0.0.1:6379> mget k5 k6
1) "v55"
2) "v66"

Hash(哈希,类似java的Map)

  1. redis hash是一个键值对集合;
  2. redis hash是一个String类型的field和value的映射表,hash特别适合用于存储对象;
  3. 类似于java中的Map<String,Object>

使用

注意:KV模式不变,但V是一个键值对

  1. hset map k v:将map的值设置成kv键值对
127.0.0.1:6379> hset user id 11
(integer) 1
127.0.0.1:6379> hget user id
"11"
  1. hmset map k1 v1 k2 v2 k3 v3:一次性为map设置多个键值对
  2. hgetall map:一次性全部获取map的键值对
127.0.0.1:6379> hmset customer id 11 name li4 age 26
OK
127.0.0.1:6379> HGETALL customer
1) "id"
2) "11"
3) "name"
4) "li4"
5) "age"
6) "26"
  1. hdel map k:将map中的键为k的键值对删除,map中没元素的话则删除map
127.0.0.1:6379> hdel user id
(integer) 1
  1. hlen map:显示map拥有的键值对个数
127.0.0.1:6379> hgetall customer
1) "id"
2) "11"
3) "name"
4) "li4"
5) "age"
6) "26"
127.0.0.1:6379> HLEN customer
(integer) 3
  1. hexists map k:判断map中是否有键为k的键值对
127.0.0.1:6379> HEXISTS customer id
(integer) 1
127.0.0.1:6379> HEXISTS customer sex
(integer) 0
  1. hkeys map:取map的所有key值
  2. hvals map:取map的所有value值
127.0.0.1:6379> hkeys  customer
1) "id"
2) "name"
3) "age"
127.0.0.1:6379> hvals customer
1) "11"
2) "li4"
3) "26"
  1. hincrby map k num:将map中k的值增加num
  2. hincrbyfloat map k floatnum:将map中的k值增加floatnum
127.0.0.1:6379> HINCRBY customer id 2
(integer) 13
127.0.0.1:6379> 
127.0.0.1:6379> HINCRBY customer id 2
(integer) 15
127.0.0.1:6379> HINCRBYFLOAT customer id 2
"17"
127.0.0.1:6379> HINCRBYFLOAT customer id 0.1
"17.1"
127.0.0.1:6379> HINCRBY customer id 2.1
(error) ERR value is not an integer or out of range
  1. hsetnx map k v:当k不存在map中时才插入此键值对
127.0.0.1:6379> HSETNX customer age 25
(integer) 0
127.0.0.1:6379> hsetnx customer email abc@126.com
(integer) 1

List(列表)

  1. redis列表是简单字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部或者尾部,他的底层是一个链表;

使用

  1. lpush list value1 value2:往list中从左push数据,从左边先进去的数据排在最后
  2. rpush list value1 value2:往list中从右push数据,从右边先进去的数据排在最前
  3. lrange list n m:从左往右显示list中从n 到m的数据,
127.0.0.1:6379> lpush list01 1 2 3 4 5 
(integer) 5
127.0.0.1:6379> LRANGE list01 0 -1
1) "5"
2) "4"
3) "3"
4) "2"
5) "1"
127.0.0.1:6379> rpush list02 1 2 3 4 5
(integer) 5
127.0.0.1:6379> LRANGE list02 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
  1. lpop list:取list左边的元素;
  2. rpop list :取list右边的元素
127.0.0.1:6379> LRANGE list01 0 -1
1) "5"
2) "4"
3) "3"
4) "2"
5) "1"
127.0.0.1:6379> lpop list01
"5"
127.0.0.1:6379> LRANGE list01 0 -1
1) "4"
2) "3"
3) "2"
4) "1"
127.0.0.1:6379> rpop list01
"1"
127.0.0.1:6379> LRANGE list01 0 -1
1) "4"
2) "3"
3) "2"
127.0.0.1:6379> 
  1. lindex list num:获取list中下标为num的元素
127.0.0.1:6379> LRANGE list01 0 -1
1) "4"
2) "3"
3) "2"
127.0.0.1:6379> LINDEX list01 0
"4"
  1. llen list :获取list的长度
127.0.0.1:6379> LRANGE list01 0 -1
1) "4"
2) "3"
3) "2"
127.0.0.1:6379> LLEN list01
(integer) 3
  1. lrem list num value:删除list中num个value值,如果不够,则有多少个删多少个
127.0.0.1:6379> rpush list03 1 1 1 2 2 2 3 3 3 4 5 6 
(integer) 12
127.0.0.1:6379> LRANGE list03 0 -1
 1) "1"
 2) "1"
 3) "1"
 4) "2"
 5) "2"
 6) "2"
 7) "3"
 8) "3"
 9) "3"
10) "4"
11) "5"
12) "6"
127.0.0.1:6379> LREM list03 2 4 
(integer) 1
127.0.0.1:6379> LRANGE list03 0 -1
 1) "1"
 2) "1"
 3) "1"
 4) "2"
 5) "2"
 6) "2"
 7) "3"
 8) "3"
 9) "3"
10) "5"
11) "6"
127.0.0.1:6379> LREM list03 2 3
(integer) 2
127.0.0.1:6379> LRANGE list03 0 -1
1) "1"
2) "1"
3) "1"
4) "2"
5) "2"
6) "2"
7) "3"
8) "5"
9) "6"
  1. ltrim list n m:截取list的第n位(包含)到第m位(包含)并重新赋给list
127.0.0.1:6379> rpush  list01 1 2 3 4 5 6 7 8
(integer) 8
127.0.0.1:6379> LRANGE list01
(error) ERR wrong number of arguments for 'lrange' command
127.0.0.1:6379> LRANGE list01 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
7) "7"
8) "8"
127.0.0.1:6379>  ltrim list01 3 5 
OK
127.0.0.1:6379> LRANGE list01 0 -1
1) "4"
2) "5"
3) "6"
  1. rpoplpush list1 list2:将list1右边的元素pop出来然后push进list2的左边
127.0.0.1:6379> LRANGE list01 0 -1
1) "4"
2) "5"
3) "6"
127.0.0.1:6379> LRANGE list02 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
127.0.0.1:6379> RPOPLPUSH list01 list02
"6"
127.0.0.1:6379> LRANGE list01 0 -1
1) "4"
2) "5"
127.0.0.1:6379> LRANGE list02 0 -1
1) "6"
2) "1"
3) "2"
4) "3"
5) "4"
6) "5"
  1. lset list index value:将list下标为index的元素替换成value
127.0.0.1:6379> LRANGE list01 0 -1
1) "4"
2) "5"
127.0.0.1:6379> lset list01 0 666
OK
127.0.0.1:6379> LRANGE list01 0 -1
1) "666"
2) "5"
  1. linsert list after/before value anothervalue:在list的元素value前或者后插入元素anothervalue
127.0.0.1:6379> LRANGE list01 0 -1
1) "666"
2) "5"
127.0.0.1:6379> LINSERT list01 before 666 999
(integer) 3
127.0.0.1:6379> LRANGE list01 0 -1
1) "999"
2) "666"
3) "5"
127.0.0.1:6379> LINSERT list01 after 666 333
(integer) 4
127.0.0.1:6379> LRANGE list01 0 -1
1) "999"
2) "666"
3) "333"
4) "5"

性能总结

  1. 它是一个字符串链表,左右都可以插入添加
  2. 如果list不存在则创建新list
  3. 如果键已经存在则增加内容
  4. 如果值全部移除则list消失
  5. 链表的操作无论对左还是右的效率都极高,但是对中间的元素操作效率很惨;

Set(集合)

  1. redis的Set是一个String类型的无序集合,他是通过hashtable实现;

使用

  1. sadd set value1,value2:往set中增加value,value如果重复不会加入
  2. smembers set:显示set的所有元素
  3. sismenber set value:判断元素是否是set的元素,是则返回1否则返回0
127.0.0.1:6379> SADD set01 1 2 3 1 2 3 
(integer) 3
127.0.0.1:6379> SMEMBERS set01
1) "1"
2) "2"
3) "3"
127.0.0.1:6379> SISMEMBER set01 1
(integer) 1
127.0.0.1:6379> SISMEMBER set01 x
(integer) 0
  1. scard set:获取set中元素的个数
127.0.0.1:6379> SCARD set01
(integer) 3
  1. srem set value:删除set中元素为value的值
127.0.0.1:6379> srem set01 3
(integer) 1
127.0.0.1:6379> SMEMBERS set01
1) "1"
2) "2"
127.0.0.1:6379> 
  1. srandmember set n:随机出n个元素,默认出一个
127.0.0.1:6379> SMEMBERS set01
 1) "0"
 2) "1"
 3) "2"
 4) "3"
 5) "4"
 6) "5"
 7) "6"
 8) "7"
 9) "8"
10) "9"
127.0.0.1:6379> SRANDMEMBER set01 
"4"
127.0.0.1:6379> SRANDMEMBER set01 
"9"
127.0.0.1:6379> SRANDMEMBER set01 
"1"
127.0.0.1:6379> SRANDMEMBER set01 3
1) "6"
2) "8"
3) "9"
  1. spop set:从set中出栈一个元素
127.0.0.1:6379> SMEMBERS set01
 1) "0"
 2) "1"
 3) "2"
 4) "3"
 5) "4"
 6) "5"
 7) "6"
 8) "7"
 9) "8"
10) "9"
127.0.0.1:6379> spop set01
"5"
127.0.0.1:6379> spop set01
"6"
127.0.0.1:6379> SMEMBERS set01
1) "0"
2) "1"
3) "2"
4) "3"
5) "4"
6) "7"
7) "8"
8) "9"
  1. smove set01 set02 value:将set01中的value值移到set02中
127.0.0.1:6379> SMEMBERS set01
1) "0"
2) "1"
3) "2"
4) "3"
5) "4"
6) "7"
7) "8"
127.0.0.1:6379> SMEMBERS set02
1) "z"
2) "y"
3) "x"
127.0.0.1:6379> SMOVE set01 set02 1
(integer) 1
127.0.0.1:6379> SMEMBERS set01
1) "0"
2) "2"
3) "3"
4) "4"
5) "7"
6) "8"
127.0.0.1:6379> SMEMBERS set02
1) "z"
2) "1"
3) "y"
4) "x"
  1. sdiff set01 set02:取set01跟set02的差集(在set01中不在set02中)
127.0.0.1:6379> sadd set01 1 2 3 4 5
(integer) 5
127.0.0.1:6379> sadd set02 1 2 a b c 
(integer) 5
127.0.0.1:6379> SDIFF set01 set02
1) "3"
2) "4"
3) "5"
  1. sunion set01 set02:取set01跟set02的并集
127.0.0.1:6379> SUNION set01 set02
1) "3"
2) "1"
3) "2"
4) "5"
5) "4"
6) "b"
7) "a"
8) "c"
  1. sinter set01 set02 :取set01根set02的交集
127.0.0.1:6379> SINTER set01 set02
1) "1"
2) "2"

Zset(sorted set:有序集合)

  1. redis zset和set一样也是string类型元素的集合切不允许有重复成员;
  2. 不同的是每个元素都会关联一个double类型的分数
  3. redis正是通过分数来为集合中的成员进行从小到大的排序。zset的成员是唯一的,但是分数却可以重复;

结构

redis配置文件中用来控制zset到底是使用ziplist(压缩双向链表)还是skiplist(跳表)的参数:

zset-max-ziplist-entries 128

zset-max-ziplist-value 64

zset-max-ziplist-entries zset使用ziplist存储的时候,最大限制存储entries的个数
zset-max-ziplist-value zset使用ziplist存储的时候,每个节点最大存储字节数

违反上述两个限制条件,均会导致zset将ziplist的数据结构切换为skiplist数据结构

而zset使用ziplist的原因,主要是出于在零散数据量少的时候,节省内容的占用

使用

  1. zadd zset01 score1 v1 score2 v2…:设置zset01的每个元素并附带分数
  2. zrange zset01 0 -1 (withscores):显示所有的元素之(附带分数)
127.0.0.1:6379> zadd zset01 60 v1 70 v2 80 v3 90 v4 100 v5
(integer) 5
127.0.0.1:6379> ZRANGE zset01 0 -1
1) "v1"
2) "v2"
3) "v3"
4) "v4"
5) "v5"
127.0.0.1:6379> ZRANGE zset01 0 -1 withscores
 1) "v1"
 2) "60"
 3) "v2"
 4) "70"
 5) "v3"
 6) "80"
 7) "v4"
 8) "90"
 9) "v5"
10) "100"
  1. zrangebyscore zset01 score1 score2:取zset01中分数在score1跟score2之间的值
  2. zrangebyscore zset01 (score1 (score2:取zset01中分数大于score1跟小于score2的值
  3. zrangebyscore zset01 score1 score2 limit n m :取zset01中分数在score1根score2之间的值,并从中取下标为n(包含)的值开始取m个元素
127.0.0.1:6379> ZRANGEBYSCORE zset01 70 90
1) "v2"
2) "v3"
3) "v4"
127.0.0.1:6379> ZRANGEBYSCORE zset01 70 (90
1) "v2"
2) "v3"
127.0.0.1:6379> ZRANGEBYSCORE zset01 (70 (90
1) "v3"
127.0.0.1:6379> ZRANGEBYSCORE zset01 70 90 limit 1 2
1) "v3"
2) "v4"
  1. zrem zset01 v:移除zset01中值为v的值
127.0.0.1:6379> ZRANGE zset01 0 -1
1) "v1"
2) "v2"
3) "v3"
4) "v4"
5) "v5"
127.0.0.1:6379> ZREM zset01 100
(integer) 0
127.0.0.1:6379> zrem zset01 v1
(integer) 1
127.0.0.1:6379> ZRANGE zset01 0 -1
1) "v2"
2) "v3"
3) "v4"
4) "v5"
127.0.0.1:6379> 
  1. zcard zset01:获取zset01中元素个数(不包含分数)
127.0.0.1:6379> zcard zset01
(integer) 4
  1. zcount zset01 score1 score2:统计zset01中score1到score2的值得个数
127.0.0.1:6379> ZCOUNT zset01 60 80
(integer) 2
  1. zrank zset01 v:获取zset01的v的下标值
  2. zscore zset01 v:获取zset01的v的分数
  3. zrevrank zset01 v:获取zset01的v的逆序下标
127.0.0.1:6379> ZRANGE zset01 0 -1 withscores
1) "v2"
2) "70"
3) "v3"
4) "80"
5) "v4"
6) "90"
7) "v5"
8) "100"
127.0.0.1:6379> ZRANK zset01 v3
(integer) 1
127.0.0.1:6379> zscore zset01 v3
"80"
127.0.0.1:6379> ZREVRANK zset01 v3
(integer) 2
  1. zrevrange zset01 0 -1 :逆序取所有的zset01 的元素值
127.0.0.1:6379> ZREVRANGE zset01 0 -1
1) "v5"
2) "v4"
3) "v3"
4) "v2"
  1. zrevrangebyscore zset01 score1 score2:取zset01中分数从score1到score2的值,注意:这里是按顺序从score1到score2并不是取大于score1小于score2的值
127.0.0.1:6379> ZREVRANGEBYSCORE zset01 60 90
(empty list or set)
127.0.0.1:6379> ZREVRANGEBYSCORE zset01 90 60
1) "v4"
2) "v3"
3) "v2"
127.0.0.1:6379> ZREVRANGEBYSCORE zset01 90 60 withscores
1) "v4"
2) "90"
3) "v3"
4) "80"
5) "v2"
6) "70"

从哪儿去获取redis命令

  1. https://redisdoc.com

redis.conf

单位

include

general

  1. Daemonize
  2. pidfile
  3. port
  4. tcp-backlog
  5. timeout
  6. bind
  7. tcp-keepalive
  8. loglevel
  9. logfile
  10. syslog-enabled
  11. syslog-ident
  12. syslog-facility
  13. databases

snapshotting 快照

  1. 默认快照位置在安装目录,与redis.conf同级(不是备份的redis.conf,是自带的)
  2. 检查redis是否启动的三种方式:
    1. ps -ef | grep redis
    2. lsof -i :6379
    3. netstat -l |grep 6379
  3. save 秒钟 次数:表示如果在秒钟内操作了多少次则重新生成一次dump.rdb文件,默认有三种;
    1. save 900 1:表示900秒(15分钟)改动过一次
    2. save 300 10:表示300秒(5分钟)改动过10次
    3. save 60 10000:表示60秒(1分钟)改动过1万次
    4. redis中直接调用save命令可以立即备份,但是这样备份数据其他存数据的过程全部阻塞,可以使用bgsave这样既可以同时备份数据也可以同时存数据;
    127.0.0.1:6379> set k1 v1
    OK
    127.0.0.1:6379> save
    OK
    

relication 复制

security安全

  1. config set requirepass password:设置密码,这样每次执行命令之前都必须执行auth password才能执行(只需要执行一次即可);
  2. auth password:验证密码
  3. config set requirepass “”:设置密码为空则不需要密码

limits 限制

  1. maxclients:最大客户端数
  2. maxmemory:最大内存 bytes
  3. maxmemory-policy:淘汰策略(指的是到达了maxmemory之后,怎么淘汰数据)
    1. noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。
    2. allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。
    3. allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。
    4. volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。
    5. volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。
    6. volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。
    7. 过期策略(指的是key通过expire设置了过期时间到期后,redis怎么处理)比较:
      1. 定时过期:每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即清除。该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的CPU资源去处理过期的数据,从而影响缓存的响应时间和吞吐量。
      2. 惰性过期:只有当访问一个key时,才会判断该key是否已过期,过期则清除。该策略可以最大化地节省CPU资源,却对内存非常不友好。极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。
      3. 定期过期:每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。
        (expires字典会保存所有设置了过期时间的key的过期时间数据,其中,key是指向键空间中的某个键的指针,value是该键的毫秒精度的UNIX时间戳表示的过期时间。键空间是指该Redis集群中保存的所有键。)
        Redis中同时使用了惰性过期和定期过期两种过期策略。
  4. maxmemory-samples:样本数

append only mode 追加

RDB (redis database)

  1. rdb:在指定的时间间隔内将数据快照写入磁盘,恢复时将快照文件直接写入内存
  2. redis会单独创建(fork)一个子进程来进行持久化,会先将数据放入临时文件,然后整个持久化过程结束了,再用这个临时文件替换原dump文件,整个过程中,主进程时不进行io操作的,这就确保了极高的性能,如果需要大规模的数据恢复,且对数据恢复的完整性要求不是非常的高,rdb比aof方式更加高效,rdb的缺点是最后一次持久化的数据可能丢失;
  3. fork:复制一个跟当前进程一模一样的进程,并作为当前进程的子进程;
  4. 具体配置可参看配置文件中snapshot一节;
  5. 优势:
    1. 适合大规模数据的恢复(相比于aof速度更快),对数据完整性跟一致性要求不高
  6. 劣势:
    1. 在一定时间内做一次备份,如果redis备份前故障,则会丢失最后一次备份的数据;
    2. fork的时候内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑;

AOF(append only file)

  1. 日志的形式记录每个操作,将redis执行过的所有写指令记录下来(不记录读指令),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,;
  2. appendonly.aof文件跟dump.rdb文件可以同时存在,但是会先搜索aof文件;
  3. aof文件如果由于故障导致文件数据错误可以使用redis-check-aof --fix appendonly.aof修复
[root@localhost bin]# redis-check-aof --fix appendonly.aof 
0x              8b: Expected prefix '1', got: '*'
AOF analyzed: size=192, ok_up_to=139, diff=53
This will shrink the AOF from 192 bytes, with 53 bytes, to 139 bytes
Continue? [y/N]: y
Successfully truncated AOF
  1. 重写:AOF采用文件追加模式,文件会越来越大,为了避免这种情况,新增了重写机制,当AOF文件的大小超过指定的阈值时,redis会启动AOD内容压缩,只保留可以恢复数据的最小指令集;
  2. 重写原理:AOF持续增长而过大时,会fork一条新进程将文件重写(也是先写到临时文件,再rename),遍历新进程内存中的数据,每条记录有一条set语句;重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令重新写了一个新的aof文件,这点跟快照类似;
  3. 触发机制:当aof大小是上次rewrite后的大小的一倍且文件大于64M的时候触发;
  4. 三种重写模式(也是其优势):
    1. appendfsync always:只有要数据改变立刻记录到文件中,消耗性能
    2. appendfsync everysec:每秒记录一次,一秒内宕机则丢失一秒内的数据(容易找回);
    3. appendfsync no:不同步
  5. 劣势:
    1. 相同的数据集的数据而言aof文件要远大于rdb文件,恢复速度慢与rdb;
    2. aof运行效率要慢于rdb,每秒同步策略较好,不同步效率跟rdb相同

redis的事务

  1. 序列化命令,在队列中,一次性,顺序性,排他性的执行一串命令
  2. 常用命令
    1. multi:开始事务
    2. exec:执行事务
    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379> set k1 v1
    QUEUED
    127.0.0.1:6379> set k2 v2
    QUEUED
    127.0.0.1:6379> get k2
    QUEUED
    127.0.0.1:6379> set k3 v3
    QUEUED
    127.0.0.1:6379> exec
    1) OK
    2) OK
    3) "v2"
    4) OK
    
    1. discard:取消事务
    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379> set k1 v1
    QUEUED
    127.0.0.1:6379> set k2 v2
    QUEUED
    127.0.0.1:6379> set k3 v33
    QUEUED
    127.0.0.1:6379> DISCARD
    OK
    127.0.0.1:6379> get k3
    "v3"
    
    1. watch key1,key2. …:监视一个或者多个key当事务执行前这个key被其他命令改动,则事务被打断;
    2. unwatch:取消对所有key的监视
  3. 当有一个命令出错时,整个事务取消
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> getset k3
(error) ERR wrong number of arguments for 'getset' command
127.0.0.1:6379> set k4 v4
QUEUED
127.0.0.1:6379> set k5 v5
QUEUED
127.0.0.1:6379> EXEC
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get k5
(nil)
  1. 当有一个命令出错,只出错的命令不执行,其余正常执行
127.0.0.1:6379> mget k1 k2 k3
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> INCR k1
QUEUED
127.0.0.1:6379> set k2 22
QUEUED
127.0.0.1:6379> set k3 33
QUEUED
127.0.0.1:6379> set k4 44
QUEUED
127.0.0.1:6379> EXEC
1) (error) ERR value is not an integer or out of range
2) OK
3) OK
4) OK
127.0.0.1:6379> mget k1 k2 k3 k4
1) "v1"
2) "22"
3) "33"
4) "44"
  1. 对于3,4两点的理解,3可以理解成java中的检查时异常,4可以理解成运行时异常,这样可以可理解成redis部分支持事务
  2. 通过watch命令在事务执行前监控了多个key,如果在watch之后有任何key发生变化,则整个事务都将被放弃,同时返回nullmulti-bulk应答已通知失败
  3. 一旦unwatch或者exec之后所有的监控锁都会被取消

redis复制

how

  1. 配从不配主:一个客户端建立起来就是主机,但是可以将多个主机变成从机配到同一个主机下面,使用slaveof ip 端口命令来分配从机,使用info replication来显示主从信息
127.0.0.1:6381> SLAVEOF 127.0.0.1 6379
OK
127.0.0.1:6381> 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_repl_offset:2239
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:42
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=2267,lag=0
slave1:ip=127.0.0.1,port=6381,state=online,offset=2267,lag=0
master_repl_offset:2267
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:2266
  1. 当主机死了之后,从机原地待命,还是slave,知道主机恢复从新恢复主从关系;但是当从机死了之后,从机恢复需要再配置成从机,否则自己是master;
  2. 薪火相传:master下挂一个slave,slave下面还可以继续挂slave,一次类推,可以有效的减轻master的压力;
  3. 反客为主:master死了之后,可以将其中的slave使用slaveof no one来变成master,然后将其他slave挂在他上面,原master恢复之后还是master只不过只有一个主机没有从机;

复制原理

  1. slave连接成功之后像master发送一个sync同步命令
  2. master接受到命令传送整个数据文件给到slave用以完成一次同步(全量同步)
  3. master陆续将新的接受的修改命令以及数据传到slave完成同步(增量同步)
  4. 但是一旦重新连接还是要执行一次全量同步
  5. 复制的缺点:复制有一定的延迟,如果从机很多,传递的效率更低更慢

哨兵模式

  1. 在自定义/myredis目录下面新建sentinel.conf,名字不能出错
  2. 然后配置哨兵
sentinel monitor host6379(随便填写,一般主机名称即可) 127.0.0.1(ip地址) 6380(端口) 1(投票大于1则成为主机)
  1. 然后启动哨兵
redis-sentinel /myredis/sentinel.conf 
  1. 哨兵启动之后,如果master死了,则剩下的slave自动选取票数大于1的成为新的master,如果原master回来则会变成slave挂在新的master下面

结合eclipse使用

  1. 引入redis相关jar包;
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值