你想了解的redis都在这里

1.概述

1.简介

Redis是一种数据库。能够存储数据、管理数据的一种软件。
#用C语言编写的 # 开源的 # 基于内存运行并支持持久化的 #高性能的nosql数据库
Redis中的数据大部分时间都是存储在内存中,适合存储频繁访问、且数据量比较小的数据。

2.数据库发展历程

1.单机数据库时代:一个应用,一个数据库实例
2.缓存、水平切分时代
3.读写分离时代
4.分库分表时代(集群)
5.nosql时代

3.关系型 VS 非关系型

关系型数据库:oracle、mysql、DB2、sqlserver、…
非关系型数据库:彻底改变底层存储机制。不再采用关系数据模型,而是采用聚合数据结构存储数据。 redis、mongoDB、HBase、…

4.redis特点

1.支持数据持久化
2.支持多种数据结构
3.支持数据备份

2.安装/启动/关闭

1.安装

1.下载
2.解压 tar-zxvf …
3.编译: make
需要先安装gcc
编译结果:在redis的安装目录下src目录中,生成redis的一系列可执行文件。
4.make install
把redis的安装目录下src目录中生成redis的一系列可执行文件拷贝到/usr/local/bin中,把任何目录下都可以执行redis命令

2.启动

1.前台启动:在任何目录下执行 redis-server
2.后台启动:在任何目录下执行 redis-server &
3.启动redis服务时,指定配置文件:redis-server redis.conf &

3.关闭

1)、通过kill命令:
ps -ef|grep redis查看pid
kill -9 pid
2)、通过redis-cli命令关闭:
redis-cli shutdown

3.redis客户端

用来连接redis服务,向redis服务端发送命令,并且显示redis服务处理结果。
redis-cli: 是redis自带客户端,使用命令redis-cli就可以启动redis的客户端程序。
命令:

  1. redis-cli:默认连接127.0.0.1(本机)的6379端口上的redis服务。
  2. redis-cli -p 端口号:连接127.0.0.1(本机)的指定端口上的redis服务。
  3. redis-cli -h ip地址 -p 端口:连接指定ip主机上的指定端口的redis服务。
  4. 退出客户端:exit或者quit

4.redis基本知识

  1. 1)、测试redis服务的性能: redis-benchmark
  2. 2)、查看redis服务是否正常运行: ping 如果正常—pong
  3. 3)、查看redis服务器的统计信息:
    info 查看redis服务的所有统计信息
    info [信息段] 查看redis服务器的指定的统计信息,如:info Replication
  4. 4)、redis的数据库实例:
    a. 作用类似于mysql的数据库实例, redis中的数据库实例只能由redis服务来创建和维护, 开发人员不能修改和自行创建数据库实例;
    b. 默认情况下,redis会自动创建16个数据库实例, 并且给这些数据库实例进行编号,从0开始,一直到15,使用时通过编号来使用数据库;
    c. 如果16个不够用,也可以通过配置文件,指定redis自动创建的数据库个数;
    d. redis的每一个数据库实例本身占用的存储空间是很少的,所以也不会造成存储空间的太多浪费。
    e. 默认情况下,redis客户端连接的是编号是0的数据库实例;可以使用select index切换数据库实例。
  5. 5)、查看当前数据库实例中所有key的数量:dbsize
  6. 6)、查看当前数据库实例中所有的key:keys *
  7. 7)、清空数据库实例:flushdb
  8. 8)、清空所有的数据库实例:flushall
  9. 9)、查看redis中所有的配置信息:config get *
    查看redis中的指定的配置信息:config get parameter

5. redis数据结构

  1. String 单key : 单value
  2. list 单key :多有序value 这里的顺序是由存放的时候决定的
  3. set 单key :多无序value
  4. hash 单key :对象
  5. zset 单key :多有序value 这里的顺序不由存放的时候决定。zset的每个元素都会关联一个分数(分数可以重复),redis通过分数来为集合中的成员进行从小到大的排序。

6. redis中的操作命令

1.有关key的操作命令

  1. a)查看数据库中的key:keys pattern
    *:匹配0个或者多个字符
    ?: 匹配1个字符
    []:匹配[]里边的1个字符
  2. b)判断key在数据库中是否存在
    exists key 如果存在,则返回1;如果不存在,则返回0
    exists key [key key …] 返回值是存在的key的数量
  3. c)移动指定key到指定的数据库实例:move key index
  4. d)查看指定key的剩余生存时间:ttl key
    如果key没有设置生存时间,表示永不过期,返回-1
    如果key不存在,返回-2
  5. e)设置key的最大生存时间:expire key seconds
  6. f)查看指定key的数据类型:type key
  7. g)重命名key: rename key newkey
  8. h)删除指定的key:del key [key key …]

2. 有关string类型数据的操作命令

  1. a)将string类型的数据设置到redis中:set 键 值
    如果key已经存在,则后来的value会把以前的value覆盖掉.
  2. b)从redis中获取string类型的数据:get 键
  3. c)追加字符串:append key value
    返回追加之后的字符串长度;
    如果key不存在,则新创建一个key,并且把value值设置为value
  4. d)获取字符串数据的长度:strlen key
  5. e)将字符串数值进行加1运算:incr key
    返回加1运算之后的数据;
    如果key不存在,首先设置一个key,值初始化为0,然后进行incr运算;
    要求key所表示value必须是数值,否则,报错。
  6. f)将字符串数值进行减1运算:decr key
    返回减1运算之后的数据;
    如果key不存在,首先设置一个key,值初始化为0,然后进行decr运算;
    要求key所表示value必须是数值,否则,报错。
  7. g)将字符串数值进行加offset运算:incrby key offset
    返回加offset运算之后的数据;
    如果key不存在,首先设置一个key,值初始化为0,然后进行incrby运算;
    要求key所表示value必须是数值,否则,报错。
  8. h)将字符串数值进行减offset运算:decrby key offset
    返回减offset运算之后的数据;
    如果key不存在,首先设置一个key,值初始化为0,然后进行decrby运算;
    要求key所表示value必须是数值,否则,报错。
  9. 闭区间获取字符串key中从start到end的字符组成的子字符串:getrange key startIndex endIndex
    下标自左至右,从0开始,依次往后,最后一个字符的下标是字符串长度-1;
    字符串中每一个下标也可以是负数,负下标表示自右至左,从-1开始,依次往前,最右边一个字符的下标是-1。
  10. j)用value覆盖从下标为startIndex开始的字符串,能覆盖几个字符就覆盖几个字符:setrange key startIndex value
  11. k)设置字符串数据的同时,设置它最大生命周期:setex key seconds value
  12. l)设置string类型的数据value到redis数据库中,当key不存在时设置成功,否则,则放弃设置:setnx key value
  13. m)批量将string类型的数据设置到redis中:mset 键1 值1 键2 值2 …
  14. n)批量从redis中获取string类型的数据:mget 键1 键2 键3…
  15. o)批量设置string类型的数据value到redis数据库中,当所有key都不存在时设置成功,否则(只要有一个已经存在),则全部放弃设置:msetnx 键1 值1 键2 值2 …

3.有关list类型数据的操作命令

概述:
一个key对应多个value;
多个value之间有顺序,最左侧是表头,最右侧是表尾;
每一个元素都有下标,表头元素的下标是0,依次往后排序,最后一个元素下标是列表长度-1;
每一个元素的下标又可以用负数表示,负下标表示从表尾计算,最后一个元素下标用-1表示;
元素在列表中的顺序或者下标由放入的顺序来决定。

  1. a)将一个或者多个值依次插入到列表的表头(左侧):lpush key value [value value …]
  2. b)获取指定列表中指定下标区间的元素:lrange key startIndex endIndex
  3. c)将一个或者多个值依次插入到列表的表尾(右侧):rpush key value [value value …]
  4. d)从指定列表中移除并且返回表头元素:lpop key
  5. e)从指定列表中移除并且返回表尾元素:rpop key
  6. f)获取指定列表中指定下标的元素:lindex key index
  7. g)获取指定列表的长度:llen key
  8. h)根据count值移除指定列表中跟value相等的数据:lrem key count value
    count>0:从列表的左侧移除count个跟value相等的数据;
    count<0:从列表的右侧移除count个跟value相等的数据;
    count=0:从列表中移除所有跟value相等的数据。
  9. i)截取指定列表中指定下标区间的元素组成新的列表,并且赋值给key:ltrim key startIndex endIndex
  10. j)将指定列表中指定下标的元素设置为指定值: lset key index value
  11. k)将value插入到指定列表中位于pivot元素之前/之后的位置: linsert key before/after pivot vlaue
    key不存在返回0;
    没有找到pivot返回 -1

4.有关set类型数据的操作命令

概述:
一个key对应多个vlaue;
value之间没有顺序,并且不能重复。

  1. a)将一个或者多个元素添加到指定的集合中:sadd key value [value value …]
    如果元素已经存在,则会忽略。
    返回成功加入的元素的个数。
  2. b)获取指定集合中所有的元素:smembers key
  3. c)判断指定元素在指定集合中是否存在:sismember key member
    存在,返回1;
    不存在,返回0
  4. d)获取指定集合的长度:scard key
  5. e)移除指定集合中一个或者多个元素:srem key member [member …]
    不存在的元素会被忽略;
    返回成功成功移除的个数。
  6. f)随机获取指定集合中的一个或者多个元素:srandmember key [count]
    count>0:随机获取的多个元素之间不能重复;
    count<0: 随机获取的多个元素之间可能重复;
    应用场景:抽奖
  7. g)从指定集合中随机移除一个或者多个元素:spop key [count]
  8. h)将指定集合中的指定元素移动到另一个集合:smove source dest member
  9. i)获取第一个集合中有、但是其它集合中都没有的元素组成的新集合:sdiff key key [key key …](差集)
  10. j)获取所有指定集合中都有的元素组成的新集合:sinter key key [key key …](交集)
  11. k)获取所有指定集合中所有元素组成的大集合:sunion key key [key key …](并集)

5.有关hash类型数据的操作命令

  1. a)将一个或者多个field-vlaue对设置到哈希表中:hset key filed1 value1 [field2 value2 …]
    如果key field已经存在,把value会把以前的值覆盖掉
  2. b)获取指定哈希表中指定field的值:hget key field
  3. c)批量将多个field-value对设置到哈希表中: hmset key filed1 value1 [field2 value2 …]
  4. d)批量获取指定哈希表中的field的值:hmget key field1 [field2 field3 …]
  5. e)获取指定哈希表中所有的field和value:hgetall key
  6. f)从指定哈希表中删除一个或者多个field:hdel key field1 [field2 field3 …]
  7. g)获取指定哈希表中所有的filed个数:hlen key
  8. h)判断指定哈希表中是否存在某一个field:hexists key field
  9. i)获取指定哈希表中所有的field列表:hkeys key
  10. j)获取指定哈希表中所有的value列表:hvals key
  11. k)对指定哈希表中指定field值进行整数加法运算:hincrby key field int
  12. l)对指定哈希表中指定field值进行浮点数加法运算:hincrbyfloat key field float
  13. m)将一个field-vlaue对设置到哈希表中,当key-field已经存在时,则放弃设置;否则,设置field-value:hsetnx key field value

6.有关zset类型数据的操作命令

概述:
有序集合,本质上是集合,所有元素不能重复;
每一个元素都关联一个分数,redis会根据分数对元素进行自动排序;
分数可以重复;
既然有序集合中每一个元素都有顺序,那么也都有下标;
有序集合中元素的排序规则与列表中元素的排序规则不一样。

  1. a)将一个或者多个member及其score值加入有序集合:zadd key score member [score member …]
    如果元素已经存在,则会把分数覆盖
  2. b)获取指定有序集合中指定下标区间的元素:zrange key startIndex endIndex [withscores]
  3. c)获取指定有序集合中指定分数区间(闭区间)的元素:zrangebyscore key min max [withscores]
  4. d)删除指定有序集合中一个或者多个元素:zrem key member [member…]
  5. e)获取指定有序集合中所有元素的个数:zcard key
  6. f)获取指定有序集合中分数在指定区间内的元素的个数:zcount key min max
  7. g)获取指定有序集合中指定元素的排名(排名从0开始): zrank key member
  8. h)获取指定有序集合中指定元素的分数:zscore key member
  9. i)获取指定有序集合中指定元素的排名(按照分数从大到小的排名): zrevrank key member

7.redis配置文件

1.概述

在redis根目录下提供redis.conf配置文件;可以配置一些redis服务端运行时的一些参数;
如果不使用配置文件,那么redis会按照默认的参数运行;
如果使用配置文件,在启动redis服务时必须指定所使用的配置文件。

2. 网络配置

  1. 1、port:指定redis服务所使用的端口,默认使用6379
  2. 2、bind: 配置客户端连接redis服务时,所能使用的ip地址,默认可以使用redis服务所在主机上任何一个ip都可以; 一般情况下,都会配置一个ip,而且通常是一个真实ip。
    如果配置了port和bind,则客户端连接redis服务时,必须指定端口和ip。
    例如: redis-cli -h 192.168.11.128 -p 6380
    redis-cli -h 192.168.11.128 -p 6380 shutdown
  3. 3、tcp-keepalive:连接保活策略
    假如设置为60秒,则server端会每60秒向连接空闲的客户端发起一次ACK请求,以检查客户端是否已经挂掉,对于无响应的客户端则会关闭其连接。如果设置为0,则不会进行保活检测。

3.常规配置

  1. loglevel: 配置日志级别,开发阶段配置debug,上线阶段配置notice或者warning.
  2. logfile:指定日志文件。
    redis在运行过程中,会输出一些日志信息;
    默认情况下,这些日志信息会输出到控制台;
    我们可以使用logfile配置日志文件,使redis把日志信息输出到指定文件中。
  3. databases:配置redis服务默认创建的数据库实例个数,默认值是16。

4.安全配置

  1. requirepass:设置访问redis服务时所使用的密码;默认不使用。
  2. 此参数必须在protected-mode=yes时才起作用。
  3. 一旦设置了密码验证,客户端连接redis服务时,必须使用密码连接:redis-cli -h ip -p port -a pwd

8.redis的持久化

1.概述

redis提供持久化策略,在适当的时机采用适当手段把内存中的数据持久化到磁盘中,每次redis服务启动时,都可以把磁盘上的数据再次加载内存中使用。

2.RDB策略

在指定时间间隔内,redis服务执行指定次数的写操作,会自动触发一次持久化操作。RDB策略是redis默认的持久化策略,redis服务开启时这种持久化策略就已经默认开启了。
save :配置持久化策略
dbfilename:配置redis RDB持久化数据存储的文件
dir: 配置redis RDB持久化文件所在目录

3.AOF策略

采用操作日志来记录进行每一次写操作,每次redis服务启动时,都会重新执行一遍操作日志中的指令。
由于每次进行写操作都要把redis指令写到操作日志中,而操作日志是在磁盘上,因此该策略会导致redis效率低下。redis默认不开启AOF功能。
appendonly:配置是否开启AOF策略
appendfilename:配置操作日志文件

9.redis事务

1.概述

事务:把一组数据库命令放在一起执行,保证操作原子性,要么同时成功,要么同时失败。
Redis的事务:允许把一组redis命令放在一起,把命令进行序列化,然后一起执行,保证部分原子性。

2.相关命令

  1. 1)multi:用来标记一个事务的开始。
  2. 2)exec:用来执行事务队列中所有的命令。
  3. 3)redis的事务只能保证部分原子性
    a)如果一组命令中,有在压入事务队列过程中发生错误的命令,则本事务中所有的命令都不执行,能够保证事务的原子性。
    b)如果一组命令中,在压入队列过程中正常,但是在执行事务队列命令时发生了错误,则只会影响发生错误的命令,不会影响其它命令的执行,不能够保证事务的原子性。
  4. 4)discard:清除所有已经压入队列中的命令,并且结束整个事务。
  5. 5)watch:监控某一个键,当事务在执行过程中,此键代码的值发生变化,则本事务放弃执行;否则,正常执行。
  6. 6)unwatch:放弃监控所有的键。

10.redis的消息发布与订阅(不常用)

1.概述

redis客户端订阅频道,消息的发布者往频道上发布消息,所有订阅此频道的客户端都能够接受到消息。

2.相关命令

  1. 1)subscribe:订阅一个或者多个频道的消息。
  2. 2)publish:将消息发布到指定频道
  3. 3)psubcribe:订阅一个或者多个频道的消息,频道名支持通配符。

11.redis的主从复制

1.搭建一主二从redis集群

操作步骤:

  1. 1)、搭建三台redis服务:使用一个redis模拟三台redis服务
    修改配置:
    bind 127.0.0.1
    port 6379
    pidfile /var/run/redis_6379.pid
    logfile “6379.log”
    dbfilename dump6379.rdb
    指定配置文件启动
    redis-server redis6379.conf &
    1. 通过redis客户端分别连接三台redis服务
      redis-cli -h 127.0.0.1 -p 6379
  2. 3)查看三台redis服务在集群中的主从角色
    info replication
    默认情况下,所有的redis服务都是主机,即都能写和读,但是都还没有从机
  3. 4)先在6379进行写操作
    此时三台redis服务互相独立,互不影响。
  4. 5)设置主从关系:设从不设主
    在6380上执行:slaveof 127.0.0.1 6379
    在6381上执行:slaveof 127.0.0.1 6379
  5. 6)全量复制:一旦主从关系确定,会自动把主库上已有的数据同步复制到从库。
  6. 7)增量复制:主库写数据会自动同步到从库。
  7. 8)主写从读,读写分离: 在从库上执行写操作会报错。
  8. 9)主机宕机、从机原地待命
  9. 10)、主机恢复、一切恢复正常
  10. 11)、从机宕机、主机少一个从机、其它从机不变
  11. 12)、从机恢复、需要重新设置主从关系
  12. 13)、从机上位
    a)主机宕机、从机原地待命
    b)从机断开原来主从关系: 在6380上执行:slaveof no one
    c)重新设置主从关系: 在6381上执行:slaveof 127.0.0.1 6380
    d)之前主机恢复、变成孤家寡人
    e)天堂变地狱
    将6379变成从机的从机,在6379上执行:slaveof 127.0.0.1 6381;
    在6381上执行:info replication,此时6381既是主机,又是从机
    小结:
    一台主机配置多台从机,一台从机又可以配置多台从机,从而形成一个庞大的集群架构。
    虽然减轻了一台主机的压力,但是增加了服务间的延迟时间。

2.redis哨兵模式

1.概述

哨兵服务负责监控redis master和slave 进程是否正常工作。如果主机宕机,会通过选举机制自动选择一个从机上位成为新主机,其余从机从属于新主机。

2.步骤

  1. 1)搭建一主二从集群架构:(上一小节前五步)
  2. 2)提供哨兵配置文件
    在redis安装目录下创建配置文件:redis_sentinel.conf;
    配置文件中配置 sentinel monitor dc-redis 127.0.0.1 6379 1
  3. 3)启动哨兵服务: redis-sentinel redis_sentinel.conf
  4. 4)主机宕机: 哨兵程序自动选择从机上位。(投票机制)
  5. 5)之前主机恢复:自动从属于新的主机。

3.小结

redis主从结构集群的特点:主少从多、主写从读、读写分离、主写同步复制到从
缺点:Redis的主从复制最大的缺点就是延迟,主机负责写,从机负责备份,这个过程有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,从机数量的增加也会使这个问题更加严重。

12.java操作redis

1.概述

jedis是redis官方提供的操作redis数据的技术。把所有的redis指令都定义成java工具类的方法,方法名和redis的指令名完全一样;开发通过程序访问redis,只需要使用工具类及其方法即可。

2. maven坐标

<dependency>
	<groupId>redis.clients</groupId>
	<artifactId>jedis</artifactId>
	<version>3.1.0</version>
</dependency>

13.缓存异常

1.缓存雪崩

缓存雪崩是指缓存同一时间大面积的失效,所以,大量的请求直接落到数据库上,造成数据库短时间内承受大量请求而崩掉。

解决方案:

  1. 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
  2. 一般并发量不是特别多的时候,使用最多的解决方案是加锁排队。
  3. 给每一个缓存数据增加相应的缓存标记,记录缓存的是否失效,如果缓存标记失效,则更新数据缓存。

2.缓存穿透

缓存穿透是指缓存和数据库中都没有的数据,导致所有的请求都落到数据库上,造成数据库短时间内承受大量请求而崩掉。

解决方案:

  1. 接口层增加参数校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;
  2. 从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击;
  3. 采用布隆过滤器(Bloom Filter),将所有可能存在的数据哈希到一个足够大的 bitmap 中,一个一定不存在的数据会被这个 bitmap 拦截掉,从而避免了对数据库的查询压力。

3.缓存击穿

一个热点key,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个完好无损的桶上凿开了一个洞。

解决方案:

  1. 设置热点数据永不过期。
  2. 加互斥锁。
    对缓存查询加锁,如果KEY不存在,就加锁,然后查DB入缓存,然后解锁;其他进程如果发现有锁就等待,然后等解锁后返回数据或者进入DB查询。

4.缓存预热

缓存预热就是系统上线后,将相关的缓存数据直接加载到缓存系统。这样就可以避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据!

解决方案:

  1. 直接写个缓存刷新页面,上线时手工操作一下;
  2. 数据量不大,可以在项目启动的时候自动进行加载;
  3. 定时刷新缓存。

5.缓存降级

当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损服务。系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级。

缓存降级的最终目的是保证核心服务可用,即使是有损的。而且有些服务是无法降级的(如加入购物车、结算)。

在进行降级之前要对系统进行梳理,看看系统是不是可以丢卒保帅;从而梳理出哪些必须誓死保护,哪些可降级;比如可以参考日志级别设置预案:

  1. 一般:比如有些服务偶尔因为网络抖动或者服务正在上线而超时,可以自动降级;
  2. 警告:有些服务在一段时间内成功率有波动(如在95~100%之间),可以自动降级或人工降级,并发送告警;
  3. 错误:比如可用率低于90%,或者数据库连接池被打爆了,或者访问量突然猛增到系统能承受的最大阀值,此时可以根据情况自动降级或者人工降级;
  4. 严重错误:比如因为特殊原因数据错误了,此时需要紧急人工降级。

服务降级的目的,是为了防止Redis服务故障,导致数据库跟着一起发生雪崩问题。因此,对于不重要的缓存数据,可以采取服务降级策略,例如一个比较常见的做法就是,Redis出现问题,不去数据库查询,而是直接返回默认值给用户。

14.redis实现分布式锁

todo

15.最经典的KV、DB读写模式

  1. 读的时候,先读缓存,缓存没有的话,再读数据库,然后取出数据后放入缓存,同时返回响应;
  2. 写的时候,先更新数据库,然后将缓存中的相应key置为失效。

16.redis VS memcache

todo

感谢

文章中第13小节的内容来源于:
原文链接:https://blog.csdn.net/ThinkWon/article/details/103522351

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

邓不利东

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值