redis

redis的特点以及安装使用

  redis是开源,BSD许可,高级的key-value存储系统,可以用来存储字符串、哈希结构、链表、集合,因此常用来提供数据结构服务。

  下载安装

    1、到官网(https://redis.io/)下载稳定版本

    2、解压安装包

    3、解压之后进入目录(/home/xdl/redis-2.8.3/src)执行make命令

    4、执行安装命令:make PREFIX=/home/xdl/redis install , /home/xdl/redis为安装目录

    5、安装完成之后在/home/xdl/redis/bin目录下出现如下5个文件

      1、redis-benchmark:性能测试工具

      2、redis-check-aof: 日志文件检测工具(比如断电造成日志损坏,可以检测并修复)

      3、redis-check-dump:快照文件检测工具,效果同上

      4、redis-cli: 连接用的客户端

      5、redis-server: redis服务进程

    6、复制配置文件:xdl@xdl-gj:~/redis/bin$ cp ../../redis-2.8.3/redis.conf  ./

    7、启动服务:xdl@xdl-gj:~/redis/bin$ ./redis-server ./redis.conf

      如果想要以后台进程的形式运行,需要修改redis.conf配置文件中的daemonize no为daemonize yes

      再次启动服务,使用ps -aux | grep redis可以查看是否成功启动

      xdl      18203  0.0  0.0  46100  3408 ?        Ssl  00:59   0:00 ./redis-server *:6379

    8、连接服务:xdl@xdl-gj:~/redis/bin$ ./redis-cli -h localhost -p 6379

      set name xdl : 设置键值

      get name:       获取name键的值

    说明:在redis.conf配置文件中databases 16,表示含有16个数据库,标号是0~15,通过select 0选择使用的数据库,默认是0

通用key操作命令

  1、del key1 key2 ... keyn

    作用:删除1个或多个键

    返回值:不存在的key忽略掉,返回真正删除的key的数量

  2、rename key newkey

    作用:给key赋一个新的key名

    说明:newkey已经存在,则newkey的原值将会被覆盖

  3、renamenx key newkey

    作用:把key改名为newkey

    返回值:发生修改返回1,未发生修改返回0

    说明:nx(not exists),即newkey不存在时才可以修改

  4、move key db

    作用:将当前数据库中的key移动到db数据中,db一般用数字代表

    返回值:移动成功返回1,移动失败返回0

    说明:一次只能移动一个key

  5、keys pattern

    作用:查询响应的key

    返回值:返回查询到的key

    说明:pattern支持模糊查询,*表示任意多个字符,?表示任意一个字符,[]表示括号内某一个字符,字符之间不需要分割符

  6、randomkey

    作用:随机返回某个key

  7、exists key

    作用:查看某个可以时候存在

    返回值:存在返回1.不存在返回0

  8、type key

    作用:查看某个可以的数据类型

    返回值:key存储的值的数据类型,包括sting、link、set、order set, hash

  9、expire key 整型值

    作用:设置key的生命周期,以秒为单位

  10、pexpire key 整型值

    作用:设置key的生命周期,以毫秒为单位

  11、persist key

    作用:把指定的key设置为永久有效

  12、ttl key

    作用:查询key的生命周期

    返回:以秒为单位的数值

    说明:对于不存在的key或已经过期/永久有效的key都返回-1,redis2.8中对于不存在或已经失效的返回-2,对用永久有效的返回-1

  13、pttl key  

    作用:查询key的生命周期

    返回:以毫秒为单位的数值

    说明:同上

字符串类型的操作

  1、set key value [ex 秒数]/ [px毫秒数] [nx]/[xx]

    作用:设置key的值

    说明:ex px同时存在时以后面的为准,nx表示key不存在的时候执行,xx表示key存在的时候执行

  2、mset key1 value1 key2 value2 ...

    作用:同时设置多个key的值

  3、get key

    作用:获取key的值

  4、mget key1 key2 ... keyn

    作用:获取多个key的值

  5、setrange key offset value

    作用:把字符串的offset偏移字节改成value,下标从0开始

    返回值:返回字符串的长度

    说明:如果offset大于字符长度,则自动补\x00

      127.0.0.1:6379> set name xdl
      OK
      127.0.0.1:6379> setrange name 4 gj
      (integer) 6
      127.0.0.1:6379> get name
      "xdl\x00gj"

  6、append key value

    作用:把value追加到key的原值上

    返回值:返回字符串的长度  

  7、getrange key start stop

    作用:获取字符串[start, stop]的范围值,闭区间

    说明:对于字符串左边从0开始右边从-1开始

  8、getset key newvalue

    作用:获取并返回旧值,设置新值

  9、incr key

    作用:指定的key的值加1

    返回值:返回加1之后的值

    说明:执行对为整数数值类型的字符串进行加1操作,对于不存在的key当做0,再incr操作

  10、incrby key number

    作用:指定的key的值加number

  11、incrbyfloat key floatnumber

    作用:加的数值可以是浮点数值

  12、decr key  

    作用:对指定的key的值做减1操作

  13、decrby key number

    作用:指定的key的值做减number操作

  14、getbit key offset

    作用:获取值的二进制表示,对应位上的值(从左,从0编号)

  15、setbit key offset value

    作用:设置offset对应二进制位上的值

    返回值:返回该位的旧值

    说明:如果offset过大,则会在中间填充0,offset最大为2^32-1,可推出最大的字符串为521M

    练习:将大写字母转换为小写字母

      分析:A对应的ascci为65,对应的二进制0100 0001,a对应的ascii为97(65+32),对应的二进制01100 0001

      127.0.0.1:6379> set char A
      OK
      127.0.0.1:6379> setbit char 2 1
      (integer) 0
      127.0.0.1:6379> get char
      "a"
  16、bitop operation destkey key1 [key2 ....]

    作用:对key1,key2,keyn做operation操作,并将结果保存到destkey上,operation可以是:AND、OR、NOT、XOR,操作符不区分大小写

    说明:NOT操作,key不能多个

    127.0.0.1:6379> setbit lower 2 1
    (integer) 0
    127.0.0.1:6379> get lower
    " "
    127.0.0.1:6379> set char Q
    OK
    127.0.0.1:6379> bitop or char char lower
    (integer) 1
    127.0.0.1:6379> get char
    "q"
    127.0.0.1:6379> set ch A
    OK
    127.0.0.1:6379> bitop OR ch ch lower
    (integer) 1
    127.0.0.1:6379> get ch
    "a"
    说明:任意一个大写字母与lower(0010 0000)做or操作就会得到小写字母

link(list)链表结构

  1、lpush key value1 value2 ... valuen

    作用:把值插入到链表的头部(左边)

    返回值:链表的长度

  2、rpush key value1 value2 ...valuen

    作用:把值插入到链表的尾部(右边)

    返回值:链表的长度

  3、lpop key  

    作用:返回并删除链表的尾元素

  4、rpop key

    作用:返回并删除链表的头部元素

  5、lrange key start stop

    作用:返回链表中[start, stop]中的元素

    说明:左边从0开始,右边从-1开始

  6、lrem key count value

    作用:删除key链表中值为value的元素,count的绝对值表示删除的个数

    返回值:返回删除的个数

    说明:count > 0 表示从头删除, count < 0 表示从尾部删除, count =  0 表示全部删除

  7、ltrim key start stop

    作用:剪切key对应的链表,切[start, stop]一段,并把该段的值重新赋值给key

    127.0.0.1:6379> lrange ans 0 -1
    1) "b"
    2) "c"
    3) "b"
    4) "c"
    127.0.0.1:6379> ltrim ans 0 2
    OK
    127.0.0.1:6379> lrange ans 0 -1
    1) "b"
    2) "c"
    3) "b"
  8、lindex key index

    作用:返回index索引上面的值

  9、llen key

    作用:获取链表的长度

  10、linsert key after|before search value

    作用:在key链表中从头开始寻找‘search’元素,一旦找到将value插入到search的前面或后面

    返回值:插入成功返回链表的长度,插入失败返回-1

    127.0.0.1:6379> rpush ans a b c d
    (integer) 4
    127.0.0.1:6379> linsert ans  before b e f
    (error) ERR wrong number of arguments for 'linsert' command
    127.0.0.1:6379> linsert ans  before b e
    (integer) 5
  11、rpoplpush source dest

    作用:将soure链表的最后一个元素取出并插入到dest链表的头部

    返回值:pop出来的元素

    应用场景:为了防止pop取出值,进行某个操作失败了,但是数据丢失的事情发生

  12、brpop | rlpop key timeout

    作用:等待弹出key的头部元素或尾部元素,timeout为等待超时时间,值为0时表示永久等待,单位为秒

    返回值:返回链表的所有元素和等待时间

    应用场景:长轮询Ajax,在线聊天

集合set相关命令

  1、sadd key value1 value2 ... valuen

    作用:向key集合中增加元素

    返回值:插入元素的个数

  2、smembers key

    作用:返回集合中所有的元素

  3、srandmember key

    作用:随机返回集合中的某个元素(只是取出不会删除)

  4、sismember key value

    作用:判断value值是否在key集合中

    返回值:如果存在返回1,不存在返回0

  5、scard key  

    作用:返回集合中元素的总个数

  6、srem key value1 value2 ... valuen

    作用:删除集合中值为value1 ... valuen的元素

    返回值:返回真正删除的元素的个数,忽略不存在的元素

  7、spop key

    作用:返回并删除集合中的某个元素,体现了集合的无序性

  8、smove source dest value

    作用:将source中值为value的元素取出并删除,然后添加到dest集合中

    返回值:成功返回1,失败返回0

    说明:dest集合不存在则创建

  9、sinter key1 key2 ... keyn

    作用:求出key1 key2 ... keyn集合中的交集并返回

  10、sinterstore dest key1 key2 ... keyn

    作用:求出key1 key2 ... keyn集合中的交集并赋值给dest

  11、sunion key1 key2 ... keyn

    作用:求出key1 key2 ... keyn集合中的并集并返回

  12、sdiff key1 key2 ... keyn

    作用:求key1与key2...keyn的差集

有序集合 Order set

  1、zadd key score1 value1 .... scoren valuen

    作用:向key有序集合添加元素

    说明:score是用来排序的  

  2、zrange key start stop [withscores]

    作用:把集合排序(升序)完之后,返回[start, stop]的元素,withscores表示把score也打印出来

    说明:start=0,stop= -1 表示取出所有的元素

  3、zrevrange key start stop [withscores]

    作用:同zrange只是排序变为降序

  4、zrangebyscore key min max [withscores] [limit offset N]

    作用:将key集合升序之后,取score在[min, max]内的元素,并跳过offset个,取出N个

  5、zrevrangebyscore key max min [withscores] [limit offset N]

    作用:同zrangebyscore,只是降序排序,取值范围由大到小

  6、zcard key

    作用:返回集合元素的个数

  7、zcount key min max

    作用:返回集合元素在[min, max]之间的个数

  8、zrank key value

    作用:查询值为value元素的排名(升序,从0开始)

  9、zrevrank key value

    作用:查询值为value元素的排名(降序,从0开始)

  10、zrem key value1 ... valuen

    作用:删除集合的元素

    返回值:返回成功删除元素的个数

  11、zremrangebyscore key min max

    作用:删除score在[min, max]之间的元素

    返回值:返回成功删除元素的个数

  12、zremrangebyrank key start stop

    作用:删除名次在[start, stop]之间的元素

    返回值:返回成功删除元素的个数

  13、zinterstore dest numkeys key1 [key2... keyn] [weights weight1 [weight2... weightn]] [aggregate sum | min | max ]

    作用:就key1...keyn的交集,并对交集的score进行权重和聚合操作,把最后的结果赋值给dest

    返回值:返回新插入dest集合的元素个数

    说明:weight * score 获取新的score,sum求和,min求最大score, max求最小的score,如果dest集合原先存在元素会先将其清空,weight可以是0 负数 浮点数

    127.0.0.1:6379> zadd z1 2 a 3 b 4 c
    (integer) 3
    127.0.0.1:6379> zadd z2 3 a 4 b 5 e
    (integer) 3
    127.0.0.1:6379> zinterstore z3 2 z1 z2 weights 2 1 aggregate min
    (integer) 2
    127.0.0.1:6379> zrange z3 0 -1 withscores
    1) "a"
    2) "3"
    3) "b"
    4) "4"
Hash哈希数据类型相关命令

  1、hset key field value

    作用:把key中field域的值设为value

    说明:如果没有field域直接添加,如果有则覆盖原来field域的值

  2、hsetnx key field value

    作用:如果key中不存在field域则添加并赋值为value,如果已经存在则操作无效

    返回值:成功添加新域为1,操作无效为0

  3、hmset key field1 value1 [ ... fieldn valuen]

    作用:设置field1->N个域,对应的值是value1->N

  4、hget key field

    作用:返回key中field域的值

  5、hmget key field1 [... fieldn]

    作用:返回key中多个域对应的值

  6、hgetall key

    作用:获取key中所有的域和值

  7、hdel key field1 [...fieldn]

    作用:删除key中field...fieldn多个域

    返回值:返回删除域的个数

  8、hlen key

    作用:返回key中域的个数

  9、hexists key field

    作用:判断key中有没有field域

    返回值:存在返回1,不存在返回0

  10、hincrby key field value

    作用:把key中field域的值增加整数值value

    说明:如果key不存在,会创建一个新的哈希集域key关联,如果field域不存在,在添加并且值为0

  11、hincrbyfloat key field value

    作用:把key中field域的值增加浮点值value

    说明:同hincrby

  12、hkeys key

    作用:返回key中所有的field

  13、kvals key

    作用:返回key中所有的value

  14、hstrlen key field

    作用:返回hash指定field的value的字符串长度,如果hash或者field不存在,返回0.

    说明:3.2.0版本之后才有的命令

redis中的事务和锁的应用

  multi、exec、discard、watch是redis事务的相关命令,事务可以一次执行多个命令, 并且带有以下两个重要的保证:

    1、事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。

    2、事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。

  redis与mysql事务的对比

  Mysql                   redis                      
开启事务 start transaction multi
语句 insert、delete、update、select语句 普通命令
失败 rollback回滚 discard取消
成功 commit提交事务 exec

 

      

  

 

  说明:在multi后面的语句中,语句出错可能有两种情况

    1、语法本身就有问题,在添加到queued队列的时候就已经报错了,这种情况在exec时报错,所有的语句都得不到执行

    2、语法本身没有问题,成功的添加到了queued队列中,比如:sadd gj 1(gj是字符串类型的),这种情况exec是之后错误的语句执行失败,其他都能成功

  执行exec之后事务就会关闭

  思考:

    正在买票ticket只剩1张,票价money为100元,如果在multi之后和exec之前,票被别人买了,即ticket变为0了,应该如何观察这种情景,并不再提交

    1、悲观的想法:

      世界充满危险,肯定有人和我抢票,给ticket加锁,只有我能操作(悲观锁)

    2、乐观的想法

      没有那么多人和我抢票,因此,只需要注意有没有人更改ticket的值就可以了(乐观锁)

  redis中的事务,启用的是乐观锁,只负责检测key有没有被改动,使用watch命令给key加锁

    127.0.0.1:6379> watch tick
    OK
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379> decr tick
    QUEUED
    127.0.0.1:6379> decrby xdl 100
    QUEUED
    127.0.0.1:6379> exec
    (nil) #说明监视的tick的值发生了变化,事务取消
  watch可以同时监控多个可以:watch key1 ... keyn ,只要其中有一个key的值发生变化,则事务取消

  unwatch:取消所有watch的key

  说明:watch命令必须在multi命令之前

频道发布与消息订阅

  使用方法:

    1、订阅端:subscribe 频道名称1 ...频道名称n

    2、发布端:pulish 频道名称 发布内容

      返回值:返回有多少个订阅端

    3、订阅端可以根据pattren匹配多个频道

      psubscribe pattern

  说明:发布/订阅与key所在空间没有关系,它不会受任何级别的干扰,包括不同数据库编码。 发布在db 10,订阅可以在db 1

redis持久化配置

  redis的持久化分为两种方式

    1、快照rdb  

      在redis.conf配置文件中

      save 900 1    :表示900秒(15分钟内)有1条写入,则生成快照
      save 300 10  :表示5分钟内有10条写入,则生成快照
      save 60 10000 :表示1分钟内有10000条写入,则生成快照
      说明:这三个选项都屏蔽,则rdb被禁用,可以自己自定义生成快照的策略

      stop-writes-on-bgsave-error yes :后台备份进程出错,主进程是否停止写入

      rdbcompression yes :d导出的rdb文件是否压缩

      rdbchecksum yes :导入rdb恢复数据时,是否要检测rdb的完整型

      dbfilename dump.rdb :备份rbd的文件名

      dir ./                            :备份rdb文件的保存路径

    2、日志aof

      在redis.conf配置文件中

      appendonly no : 是否打开aof日志功能

      appendfilename appendonly.aof  : aof文件的路径加文件名,默认为appendonly.aof

      appendfsync always :每1条命令,都立刻同步到aof中,安全,但是速度慢
      appendfsync everysec :每隔1秒写入一次,比较好的方案
      appendfsync no      : 写入工作交给操作系统,由操作系统判断缓冲区大小,统一写入到aof,同步频率低(容易造成大量数据的丢失),速度快

      no-appendfsync-on-rewrite no : 正在导出rdb快照时,是否要停止同步aof

      auto-aof-rewrite-percentage 100 : aof文件大小比起上次重写的大小,增长率100%时,重写,比如上次写入后文件2M,下次写入文件为4M时将进行重写
      auto-aof-rewrite-min-size 64mb :aof文件,至少超过64M时,重写,(如果值太小,前期重写太过频繁)

  问答:

    在dumpr rdb过程中,aof如果停止同步,会不会丢失数据?

    答:不会,所有操作将会缓存在内存的队列里,dump完成后,统一操作

    aof重写指的是什么?

    答:aof重写是指把内存中的数据,逆化成命令,写入到aof日志里,以解决aof日志过大的问题,比如一个值一直增加1,我们只去最后的值

    如果rdb文件和aof文件都存在,优先使用谁进行数据恢复呢?

    答:aof,会出现rbd中有数据,但是我们重启服务之后内存中没有数据,这是因为我们启用了aof但是aof中没有数据

    两种方式是否可以同时使用

    答:可以,而且推荐这么做

    恢复数据时,哪种方式更快

    答:rdb,因为rdb是数据的内存映射,直接载入到内存,而aof是命令,需要逐条执行

redis集群

  Redis 集群是一个提供在多个Redis间节点间共享数据的程序集。就是多个redis服务器

  作用:

    1、主从备份,防止主机宕机

    2、读写分离,分担master的任务

    3、任务分离,主从服务分别分担备份工作与计算工作

  有两种方式实现

    1、              slave1

        master    ...

              slaven

    2、master <-- slave1 ... <--slaven

  方式2的好处在于master宕机之后,可以直接切换到slave1,让slave1作为master,方式1需要手动修改,或使用sentinel监控

  配置redis集群

    master配置:

      1、关闭rdb快照(备份工作交给slave),注释掉save即可

      2、可以开启aof

      3、配置密码,#  requirepass foobared,设置密码之后,启动客户端时需要输入密码

                 4、可以通过命令: config set requirepass 密码   进行设置密码

    slave配置:

      1、声明slaveof,slaveof <masterip> <masterport> 

      2、配置密码(如果master有密码), masterauth <master-password>

      3、某一个slave打开rdb快照功能

      4、配置slave只读,slave-read-only yes 

      5、配置pid文件,pidfile /var/run/redis6380.pid

      6、配置端口,port 6380 

  缺点:

    每次slave断开后,(无论是主动断开,还是网络故障)在连接master,都要master全部dump出来rdb,在aof,即同步的过程都要重新执行一遍

    所以要记住,多台slave不要一下都启动起来,否则master可能IO剧增,

  如果redist集群中master宕机,应该怎么处理

    手动处理的方式:

      1、修改一台slave(A)为master

        1、命令该服务不做其他redis服务的slave,slaveof no one

        2、修改readonly 为 no, config set slave-read-only no

      3、修改其他slave作为A服务的slave

        1、slaveof localhost 6380

    使用sentinel监控实现

      1、将sentinel.conf拷贝到安装目录(bin)下~/redis/bin$ cp ../../redis-2.8.3/sentinel.conf ./

      2、监控master并起名为mymaster(可以自定义但是后面的必须与其一致),2表示两个sentinel实例都未连接到master才是真正的宕机:

        sentinel monitor mymaster 127.0.0.1 6379 2 

      3、如果master设置的有密码,需要配置密码:sentinel auth-pass <master-name> <password>

      4、设置间隔多长时间之内得到响应则认为失败,sentinel down-after-milliseconds mymaster 30000

      5、sentinel parallel-syncs mymaster 1 :表示一次只添加一台master,否则会造成新的master IO剧增

      6、启动监控:  ./redis-server ./sentinel.conf --sentinel

      说明:sentinel根据redis.conf配置文件中的优先级选择哪个slave作为新的master(slave-priority 100),数值越小优先级越大,如果优先级相同,则随机选择。

redis key的设计技巧

  1、把表名转换为key的前缀,比如tag:

  2、第二段放置用于区分key的字段,对用mysql中的主键的列名

  3、第三段放置主键的值

  4、第四段放置要存储的列名

  说明:在关系型数据库中,还有可能其他列也经常作为查询字段,这种字段往往也是加了索引的,转为key-value数据库中,则也要相应的生成

     一条按照该列为主的key-value,根据这个可以找到对应的主键,然后在查询相应的内容

  下面看一个例子

    在MySQL数据库中创建book和tags两张表,内容如下:

      mysql> select * from book;
      +--------+----------------------+
      | bookid | title                |
      +--------+----------------------+
      |      5    | PHP 圣经             |
      |      6   | ruby 实战            |
      |      7   | mysql 运维           |
      |      8   | ruby 服务端编程      |
      +--------+----------------------+

      mysql> select * from tags;
      +------+--------+----------+
      | tid  | bookid | content  |
      +------+--------+----------+
      |   10 |      5 | PHP      |
      |   11 |      5 | WEB      |
      |   12 |      6 | WEB      |
      |   13 |      6 | ruby     |
      |   14 |      7 | database |
      |   15 |      8 | ruby     |
      |   16 |      8 | server   |
      +------+--------+----------+
  根据上面两张表,查询出既有WEB标签,又有PHP标签的书,

  select b.bookid,b.title from book as b inner join tags as t1 inner join tags as t2 on b.bookid=t1.bookid and t1.book=t2.bookid where t1.content='PHP' and t2.content='WEB';
  使用上面的连接查询确实可以获取结果,但是效率很低

  现在使用redis构造与上面两张表相同的效果

    mset book:bookid:5 PHP book:bookid:6 ruby book:bookid:7 mysql book:bookid:8 reub2

    创建标签表使用集合数据类型

      127.0.0.1:6379> sadd tags:PHP 5
      (integer) 1
      127.0.0.1:6379> sadd tags:WEB 5 6
      (integer) 2
      127.0.0.1:6379> sadd tags:ruby 6 8
      (integer) 2
      127.0.0.1:6379> sadd tags:database 7
      (integer) 1
      127.0.0.1:6379> sadd tags:server 8
      (integer) 1
  可以使用集合的交集找到既有PHP又有WEB标签的bookid

     127.0.0.1:6379> sinter tags:PHP tags:WEB
     1) "5" 

    









      

 

posted @ 2019-07-18 01:05  xdl_smile  阅读(223)  评论(0编辑  收藏  举报