Linux安装
下载地址:download.redis.io/releases/re…
安装步骤
1.下载后获得redis-5.0.7.tar.gz后,将它放在我们linux的目录下/opt
2. 解压命令:tar -zvxf redis-5.0.7.tar.gz
3.解压完成后,出现一个文件夹:redis-5.0.7
4.进入目录:cd redis-5.0.7
5. 在redis下执行make命令(需要保证linux上有gcc环境,如果没有,请安装。)
6.如果make完成后继续执行make install
7.查看默认安装目录:/usr/local/bin
/usr 是一个非常重要的目录,类似于windows下的program fils,存放用户的程序
- 拷贝一份配置文件(留下备用)
cd /usr/local/bin
ls -l
# 在redis的解压目录下备份redis.conf
mkdir myredis
cp redis.conf myredis # 拷一个备份,养成良好的习惯,我们就修改这个文件
# 修改配置保证可以后台应用
vim redis.conf
- daemonize是设置守护线程,默认是NO
- daemonize是用来指定redis是否要用守护线程的方式使用。 daemonize:yes redis采用的是单进程多线程的模式。当redis.conf中选项daemonize设置成yes时,代表开启 守护进程模式。在该模式下,redis会在后台运行,并将进程pid号写入至redis.conf选项 pidfile设置的文件中,此时redis将一直运行,除非手动kill该进程。
如果想要远程连接,那么必须再修改以下两个部分。
daemonize:no 当daemonize选项设置成no时,当前界面将进入redis的命令行界面,exit强制退出或者关闭 连接工具(putty,xshell等)都会导致redis进程退出。
- 启动测试一下
# 【shell】启动redis服务
[root@192 bin]# cd /usr/local/bin
[root@192 bin]# redis-server /opt/redis-5.0.7/redis.conf
# redis客户端连接===> 观察地址的变化,如果连接ok,是直接连上的,redis默认端口号 6379
[root@192 bin]# redis-cli -p 6379
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> set k1 helloworld OK
127.0.0.1:6379> get k1 "helloworld"
# 【shell】ps显示系统当前进程信息
[root@192 myredis]# ps -ef|grep redis
root 16005 1 0 04:45 ? 00:00:00 redis-server 127.0.0.1:6379
root 16031 15692 0 04:47 pts/0 00:00:00 redis-cli -p 6379
root 16107 16076 0 04:51 pts/2 00:00:00 grep --color=auto redis
# 【redis】关闭连接
127.0.0.1:6379> shutdown
not connected> exit
常用命令
键常用命令
1. keys *
2. set name jianyou
3. exists name //判断这个键是否存在
4. move key db //删除某个库的某个键
5. expire name 10 //设置name这个键的过期时间是10s
6. ttl name //查看name的过期时间
7. type name //查看这个键的数据结构
8. strlen key //根据key获取value长度
字符串常用命令
1. set key value //添加一个键值对
2. get key //根据键获取值
3. del key //删除这个键值对
4. append key value //如果这个key存在,那么就追加,如果存在就新建一个key,value
5. # ===================================================
# incr、decr 一定要是数字才能进行加减,+1 和 -1。
# incrby、decrby 命令将 key 中储存的数字加上指定的增量值。
# ===================================================
set views 0 //设置初始浏览量为0
incr views //浏览量+1
decr views //浏览量-1
incrby views 10 //浏览量加10
decrby views 10 //浏览量减10
6. setex key second value //设置键值对的同时设置过期时间
7. setnx key value //如果该键不存在,就创建一个,如果已经存在,就创建失败
String类型是最简单的的key-value结构,value不仅仅是String,也可以是数字,value可以存放的内容很大,可以达到512兆。 常规的key-value缓存应用:计数器,微博数,粉丝数等。
列表List常用命令
1. lpush list "one" //向列表右边加入一个数据
2. rpush list "two" //向列表左边加入一个数据
3. lpop list //移除列表的第一个元素
4. rpop list //移除列表的最后一个元素
5. lrange list 0 -1 //取出列表中的所有元素
6. lindex list 1 //取出list中对于索引位置的元素
7. llen list //返回列表的长度
8. lpoppush list otherlist //移除第一个列表中的元素并将该元素添加到另一个元素中并返回
注意redis中list的方向,这个和我们Java集合中添加的方向不太一样。记住left就是左边,right就是右边就对了!
- 它是一个字符串链表,left,right都可以插入添加
- 如果键不存在,就创建一个新的链表
- 如果键已经存在,就新增一个内容
- 如果值全部移除,对应的键也就消失了
- 链表的操作无论是头和尾的效率都极高,但是对中间元素的操作效率较低。
集合常用命令
1. sadd set "hello" //在集合中添加一个hello
2. sismember set value //判断这个值是否存在于键中
3. smembers set //查出集合中的所有元素
4. scard set //获取集合中的元素个数
5. srem set value //移除集合中的某一个或者多个元素
6 srandmember set //返回该集合中的一个随机元素
7. spop set //用于移除集合中的一个或者多个元素
8. smove set1 set2 value //将set1中的值移动到set2中去
9. =============数学集合:交并补========================
sdiff key1 key2 //两个集合的差集(key1中不同于key2的元素)
sinter key1 key2 //交集
sunion key1 key2 //并集
在微博应用中,可以将一个用户所有的关注人存在一个集合中,将其所有粉丝放在一个集合中,集合中提供了求交集,并集,差集等操作,可以非常方便的实现如共同关注,共同喜好,共同好友等功能,对上面的所有集合操作,还可以使用不同的命令选择键结果返回给客户端还是存到一个新的集合中。
哈希HASH
KV模式不变,但是v是一个键值对
hset myhash field "value" //myhash是大键,field是二次键
hget muhash field //获取field的值
hmset myhash field1 "value1" field2 "value2" //hmset可以一次设置多个值
hgetall myhash //一次获取myhash中的所有值
hdel myhash field1 //删除myhash中的对应键值对
hkeys myhash //获取到myhash中的所有键
hvals myhash //获取到哈希表的
hexists myhash field1 //判断这个键是否存在
hincrby myhash field 1 //增加对应的值
hsetnx myhash field "value" //为hash表中不存在的字段进行赋值
hash是一个String类型的field和value映射表,hash特别适合于存储对象。存储部分变更的数据,如用户信息等。
有序集合Zset
在set的基础上,添加了一个score值,之前set是k1,v1,v2,v3。现在zset是k1 score1 v1 score2 v2
zadd set 1 "one" //zset集合添加一个元素,添加的同时要指定分数,可以同时添加多个成员数量
zrange set 0 -1 //查找出集合中的所有元素
#inf表示正无穷大,负无穷大就是-inf
zrangebyscore key -inf +inf //显示整个有序集
zrangebyscore key -inf +inf withscores //递增排序
zreverange key 0 -1 withscores //递减排序
zrangebyscore key -inf 2500 withscores //显示集合中value<=2500的元素
zrem key value //移除集合中的这个元素
zcard keys 计算集合中元素的数量
zcount set score1 score2 //计算有序集合指定分数区间的成员数量
zrank key value //返回集合中这个元素的排名(按照分数值从小到大)排列。
zrevrank key value //返回集合中这个元素排名(按照分数值从大到小)排列
和set相比,zset增加了一个权重的参数score,使得集合中的元素可以按照score进行有序的排列,比如存储全班同学成绩
redis集群搭配
- 可以选择单机多集群或者多机多集群。创建多个redis环境即可。默认每一台redis都是master主机。我们进入从机的redis环境中,使用命令:slaveof 主机ip 主机端口 即可成功配置从机需要附属的主机。
- 使用命令的话只是本次服务有效,如果redis服务停止重新启动后主从的配置就会失效。如果要永久配置还是要去redis的配置文件中进行配置。
哨兵模式
哨兵是一种特殊的模式,它是一个独立的进程,会独立运行。它的实现原理就是通过向redis服务器发送命令,等待服务器响应,从而监控多个redis实例。
这里的哨兵有两个作用:
- 发送命令给所有的redis服务器,等待其返回信息,根据是否有返回信息判断是否宕机。
- 当监测到master主机宕机以后,会自动将slave切换为master,然后通过发布订阅模式,通知其他的slave,修改配置文件,让他们切换主机。
但是一个哨兵进程对于redis服务器进行监控,可能会出现问题,所以我们使用多个哨兵进行监控,多个哨兵之间也会进行监控,这就形成了多哨兵模式。
哨兵配置
- 创建一个sentinel.conf文件
- 配置哨兵,填写如下内容:
sentinel monitor 被监控主机名字 ip地址 端口号 1最后一个1是选举的票数。 - 启动哨兵:
redis-sentinel */sentinel.conf即可运行。 哨兵模式的优点:1. 哨兵模式是基于主从模式的,所有主从模式的优点,哨兵模式全部都有。 - 主从可以切换,故障可以转移,系统的可用性更好。
哨兵配置的说明
# Example sentinel.conf
# 哨兵sentinel实例运行的端口 默认26379
port 26379
# 哨兵sentinel的工作目录
dir /tmp
# 哨兵sentinel监控的redis主节点的 ip port
# master-name 可以自己命名的主节点名字 只能由字母A-z、数字0-9 、这三个字符".-_"组成。
# quorum 配置多少个sentinel哨兵统一认为master主节点失联 那么这时客观上认为主节点失联了
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 127.0.0.1 6379 2
# 当在Redis实例中开启了requirepass foobared 授权密码 这样所有连接Redis实例的客户端都
要提供密码
# 设置哨兵sentinel 连接主从的密码 注意必须为主从设置一样的验证密码
# sentinel auth-pass <master-name> <password>
sentinel auth-pass mymaster MySUPER--secret-0123passw0rd
# 指定多少毫秒之后 主节点没有应答哨兵sentinel 此时 哨兵主观上认为主节点下线 默认30秒
# sentinel down-after-milliseconds <master-name> <milliseconds>
sentinel down-after-milliseconds mymaster 30000
# 这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行 同
步,
这个数字越小,完成failover所需的时间就越长,
但是如果这个数字越大,就意味着越 多的slave因为replication而不可用。
可以通过将这个值设为 1 来保证每次只有一个slave 处于不能处理命令请求的状态。
# sentinel parallel-syncs <master-name> <numslaves>
sentinel parallel-syncs mymaster 1
# 故障转移的超时时间 failover-timeout 可以用在以下这些方面:
#1. 同一个sentinel对同一个master两次failover之间的间隔时间。
#2. 当一个slave从一个错误的master那里同步数据开始计算时间。直到slave被纠正为向正确的
master那里同步数据时。
#3.当想要取消一个正在进行的failover所需要的时间。
#4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超
时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来了
# 默认三分钟
# sentinel failover-timeout <master-name> <milliseconds>
sentinel failover-timeout mymaster 180000
# SCRIPTS EXECUTION
#配置当某一事件发生时所需要执行的脚本,可以通过脚本来通知管理员,例如当系统运行不正常时发邮
件通知相关人员。
#对于脚本的运行结果有以下规则:
#若脚本执行后返回1,那么该脚本稍后将会被再次执行,重复次数目前默认为10
#若脚本执行后返回2,或者比2更高的一个返回值,脚本将不会重复执行。
#如果脚本在执行过程中由于收到系统中断信号被终止了,则同返回值为1时的行为相同。
#一个脚本的最大执行时间为60s,如果超过这个时间,脚本将会被一个SIGKILL信号终止,之后重新执
行。
#通知型脚本:当sentinel有任何警告级别的事件发生时(比如说redis实例的主观失效和客观失效等
等),将会去调用这个脚本,这时这个脚本应该通过邮件,SMS等方式去通知系统管理员关于系统不正常
运行的信息。调用该脚本时,将传给脚本两个参数,一个是事件的类型,一个是事件的描述。如果
sentinel.conf配置文件中配置了这个脚本路径,那么必须保证这个脚本存在于这个路径,并且是可执
行的,否则sentinel无法正常启动成功。
#通知脚本
# sentinel notification-script <master-name> <script-path>
sentinel notification-script mymaster /var/redis/notify.sh
# 客户端重新配置主节点参数脚本
# 当一个master由于failover而发生改变时,这个脚本将会被调用,通知相关的客户端关于master
地址已经发生改变的信息。
# 以下参数将会在调用脚本时传给脚本:
# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
# 目前<state>总是“failover”,
# <role>是“leader”或者“observer”中的一个。
# 参数 from-ip, from-port, to-ip, to-port是用来和旧的master和新的master(即旧的
slave)通信的
缓存穿透和雪崩
缓存穿透
概念:
客户端要查询的数据在缓存中不存在,所以全部都去请求数据库,从而绕过了缓存,也给服务器造成了很大的压力。
解决方案:
1. 布隆过滤器
布隆过滤器是在1970年布隆提出来的。它实际上是一个很长的二进制向量和一系列的随机映射向量。布隆过滤器可以用来检测一个元素是否在集合中。它的优点是空间效率和查询时间都远远的超过一般的算法,缺点是有一定的误码率和删除困难。
它的原理是当一个元素被加入到集合时,通过k个散列函数将这个元素映射为一个位数组中的k个点,并将这些点置为1。检索时只需要检索一下这些点都是不是1就知道这个元素是不是位于这个集合中了。如果这些点中有任意一个位置为0,那么该元素一定不在集合中,如果这些位置都是1,则这个元素很可能在,这就是布隆过滤器的基本思想。
2. 缓存空对象
对查询不到的空对象也将其缓存起来,同时设置一个过期时间,之后再访问的时候就直接通过缓存获取,从而保护数据库。
但是这种方法会存在两个问题:
1、如果空值能够被缓存起来,这就意味着缓存需要更多的空间存储更多的键,因为这当中可能会有很多 的空值的键;
2、即使对空值设置了过期时间,还是会存在缓存层和存储层的数据会有一段时间窗口的不一致,这对于 需要保持一致性的业务会有影响。
缓存击穿
概念:指一个key非常热点,不停的扛着大并发。并且大并发集中一个点进行访问。在这个key失效的瞬间,持续的大并发就穿破缓存,直达数据库。
解决方案
- 设置热点数据永不过期
- 加互斥锁,保证,每个key同时只有一个线程去查询后端的服务
缓存雪崩
概念:指在某一个时间段内,缓存集体失效。
解决方案
- 搭建redis集群,一台redis挂掉的话其他还可以继续工作、
- 限流降级,可以使用加锁或者队列的方式来控制读数据库写缓存的线程数量。
事务
Redis也支持事务,但是Redis的事务不能保证原子性。在进入事务队列时发现的错误如语法错误等会导致整个事务取消,但是在进行exec命令之后才产生的错误不会导致整个事务取消,只是会取消产生错误的那条具体命令而已。
Redis使用事务的具体方式是:multi和exec两条命令。 multi用于开启事务,之后就可以执行我们的具体操作,开启事务后的所有操作并不会立即执行,而是会将这些命令放在一个队列之中,知道执行exec命令后,才会按照顺序逐一执行。
Redis实现乐观锁
在redis中可以使用watch命令来监视某个key,这样的话当我们执行某个事务的时候,如果发现有其他的事务修改了我们监视的这个数据,我们的事务就不会执行成功。确保了数据安全性。
我们使用两个连接来进行测试,第一个连接监视money,并开启事务修改money的值。第二个连接直接修改money的值,此时第一个连接使用exec命令执行,不会执行成功!
第一个连接:
执行结果时nil就表示这个事务执行失败了,因为在事务执行的过程中,第二个连接改变了money的值!
第二个连接:
那watch监视器的作用什么时候消失呢?当我们执行exec事务提交的命令之后就自行消失了,否则会一直存在。
常见面试题?
Redis为什么这么快?
- redis是基于内存进行操作的,省去了磁盘io所需要的时间。
- 是单线程的,避免了线程切换。
- 高效的数据结构。
- 合理的数据编码。