一、基本数据类型、介绍
设置过期,判断是否存在:这个用哪个是最好的?
用命令保证其原子性操作:set lock 1 ex 10 nx 这个命令
1、String 数据类型:
set (添加 key value)
set server:name "fido" (key为"server:name")
get
keys * (得到所有key)
exists (判断是否存在)
mset aa 2673 jack 666 (批量设置)
setnx aa (不存在就添加)
incr aa (自增++1,如果aa不存在,aa为1,每一次自增1)
incrby aa 100 (aa + 100)
decr aa (自减--1 , 每次自减1)
decrby aa 100 (aa - 100)
set f 2.6 (设置float的)
incrbyfloat f 7.3 (加法)
mget aa jack (批量取)
strlen aa (返回长度)
append aa good (拼接"good",如果aa没有,那么)
getrange aa 0 8 (截取)
del (删除)
2、list数据类型: 当value 是list数据类型:
rpush friends aaa (从右边/尾部添加数据)
lpush friends bbb (从左边/头部添加数据)
lrange friends 0 -1 (查询key的所有数据)
lrange friends 0 1 (查询0-1下标的数据)
llen friends (查询key 的value 的长度)
lpop friends (从左边删除)
rpop friends (从右边删除)
del friends
3、set 数据类型: 当value是set数据类型:
sadd supper aaa (添加value值的一个数据)
sismember supper aaa (查询数据是否存在)
srem supper aaa (删除value值的一个数据)
smembers supper (查询所有value值)
sadd star bbb
sunion supper star (只是返回value合并之后的结果,)
del
4、hash 数据类型: 当value是hash数据类型
hset user1 name xiaoming (添加value的一个数据)
hmset user1 age 2 sex 0 (批量添加)
hgetall user1 (得到所有value值)
hget user1 name (得到value中其中一个值)
hincrby user1 age 1 (原子性操作,加1)
hincrby user1 age 10 (加10)
hdel user1 age (删除value其中一个值)
del
5、key的生命周期,过期。
set lock demo
expire lock 120 (设置过期时间)
ttl lock (返回还剩的过期时长)
set lockname demoname
ttl lockname (永久不过期的返回-1)
SETEX key "seconds" "value" : set 加expire
6、设置redis密码:
config get requirepass
config set requirepass 123
redis-cli -h 127.0.0.1 -p 6379 123
二、面试整理
1、优势:
1、吞吐量大:10万每秒的请求是比较轻松的。
2、基于内存的,读写速度非常快。
3、redis 是单线程的,线程安全的,避免了不必要的上下文切换和竞争条件。
4、没有各种锁的性能消耗。
5、高并发快。
6、支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行
2、Redis相比memcached有哪些优势:
(1) memcached所有的值均是简单的字符串,redis作为其替代者,支持更为丰富的数据类型
(2) redis的速度比memcached快很多
(3) redis可以持久化其数据
(4)Redis支持数据的备份,即master-slave模式的数据备份。
(5) 使用底层模型不同,它们之间底层实现方式 以及与客户端之间通信的应用协议不一样。Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。
(6)value大小:redis最大可以达到1GB,而memcache只有1MB
3、redis的实际用途
1、计数器:
可以对String进行自增自减运算,实现计数功能。如果是在单机模式下,在读写过程中是线程安全的,redis是基于内存的,读写速度也是非常快的,很适合存储频繁读写的数据操作。
2、缓存数据
怎么保证数据安全?
3、分布式sessioin
怎么实现?
4、set ex nx 使用数据存在redis的有效时间设置做一些定时存储。
5、incr做限流
怎么做?
6、可用于缓存,消息,按key设置过期时间,过期后将会自动删除
4、redis的内部实现
内部实现采用epoll,采用了epoll+自己实现的简单的事件框架。epoll中的读、写、关闭、连接都转化成了事件,然后利用epoll的多路复用特性,绝不在io上浪费一点时间 这3个条件不是相互独立的,特别是第一条,如果请求都是耗时的,采用单线程吞吐量及性能可想而知了。应该说redis为特殊的场景选择了合适的技术方案。
5、redis 关于线程安全问题:
redis实际上是采用了线程封闭的观念,把任务封闭在一个线程,自然避免了线程安全问题,不过对于需要依赖多个redis操作的复合操作来说,依然需要锁,而且有可能是分布式锁。
6、IO多路复用
要弄清问题先要知道问题的出现原因
原因:
由于进程的执行过程是线性的(也就是顺序执行),当我们调用低速系统I/O(read,write,accept等等),进程可能阻塞,此时进程就阻塞在这个调用上,不能执行其他操作.阻塞很正常.
接下来考虑这么一个问题:一个服务器进程和一个客户端进程通信,服务器端read(sockfd1,bud,bufsize),此时客户端进程没有发送数据,那么read(阻塞调用)将阻塞,直到客户端调用write(sockfd,but,size)发来数据.在一个客户和服务器通信时这没什么问题;
当多个客户与服务器通信时当多个客户与服务器通信时,若服务器阻塞于其中一个客户sockfd1,当另一个客户的数据到达套接字sockfd2时,服务器不能处理,仍然阻塞在read(sockfd1,...)上;此时问题就出现了,不能及时处理另一个客户的服务,咋么办?
I/O多路复用来解决!
I/O多路复用:
继续上面的问题,有多个客户连接,sockfd1,sockfd2,sockfd3..sockfdn同时监听这n个客户,当其中有一个发来消息时就从select的阻塞中返回,然后就调用read读取收到消息的sockfd,然后又循环回select阻塞;这样就不会因为阻塞在其中一个上而不能处理另一个客户的消息
Q:
那这样子,在读取socket1的数据时,如果其它socket有数据来,那么也要等到socket1读取完了才能继续读取其它socket的数据吧。那不是也阻塞住了吗?而且读取到的数据也要开启线程处理吧,那这和多线程IO有什么区别呢?
A:
1.CPU本来就是线性的不论什么都需要顺序处理并行只能是多核CPU
2.io多路复用本来就是用来解决对多个I/O监听时,一个I/O阻塞影响其他I/O的问题,跟多线程没关系.
3.跟多线程相比较,线程切换需要切换到内核进行线程切换,需要消耗时间和资源.而I/O多路复用不需要切换线/进程,效率相对较高,特别是对高并发的应用nginx就是用I/O多路复用,故而性能极佳.但多线程编程逻辑和处理上比I/O多路复用简单.而I/O多路复用处理起来较为复杂.
7、Redis常见性能问题和解决方案:
(1) Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件;(Master写内存快照,save命令调度rdbSave函数,会阻塞主线程的工作,当快照比较大时对性能影响是非常大的,会间断性暂停服务,所以Master最好不要写内存快照;AOF文件过大会影响Master重启的恢复速度)
(2) 如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次
(3) 为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内
(4) 尽量避免在压力很大的主库上增加从库
(5) 主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1 <- Slave2 <- Slave3...;这样的结构方便解决单点故障问题,实现Slave对Master的替换。如果Master挂了,可以立刻启用Slave1做Master,其他不变。
8、Redis的回收策略
volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
no-enviction(驱逐):禁止驱逐数据
注意这里的6种机制,volatile和allkeys规定了是对已设置过期时间的数据集淘汰数据还是从全部数据集淘汰数据,后面的lru、ttl以及random是三种不同的淘汰策略,再加上一种no-enviction永不回收的策略。
使用策略规则:
1、如果数据呈现幂律分布,也就是一部分数据访问频率高,一部分数据访问频率低,则使用allkeys-lru
2、如果数据呈现平等分布,也就是所有的数据访问频率都相同,则使用allkeys-random
9、五种I/O模型介绍
IO 多路复用是5种I/O模型中的第3种,对各种模型讲个故事,描述下区别:
故事情节为:老李去买火车票,三天后买到一张退票。参演人员(老李,黄牛,售票员,快递员),往返车站耗费1小时。
1.阻塞I/O模型
老李去火车站买票,排队三天买到一张退票。
耗费:在车站吃喝拉撒睡 3天,其他事一件没干。
2.非阻塞I/O模型
老李去火车站买票,隔12小时去火车站问有没有退票,三天后买到一张票。
耗费:往返车站6次,路上6小时,其他时间做了好多事。
3.I/O复用模型
1.select/poll
老李去火车站买票,委托黄牛,然后每隔6小时电话黄牛询问,黄牛三天内买到票,然后老李去火车站交钱领票。
耗费:往返车站2次,路上2小时,黄牛手续费100元,打电话17次
2.epoll
老李去火车站买票,委托黄牛,黄牛买到后即通知老李去领,然后老李去火车站交钱领票。
耗费:往返车站2次,路上2小时,黄牛手续费100元,无需打电话
4.信号驱动I/O模型
老李去火车站买票,给售票员留下电话,有票后,售票员电话通知老李,然后老李去火车站交钱领票。
耗费:往返车站2次,路上2小时,免黄牛费100元,无需打电话
5.异步I/O模型
老李去火车站买票,给售票员留下电话,有票后,售票员电话通知老李并快递送票上门。
耗费:往返车站1次,路上1小时,免黄牛费100元,无需打电话
1同2的区别是:自己轮询
2同3的区别是:委托黄牛
3同4的区别是:电话代替黄牛
4同5的区别是:电话通知是自取还是送票上门
10、redis 各种数据类型的底层存储结构
1、
11、String数据类型的三种编码:
1、int ,存储8个字节的长整型(long, 2^63-1)
2、embstr, embstr 格式的SDS(simple dynamic String)
3、raw , SDS ,存储大于44个字节的字符串
12、怎么动态存储?
13、SDS相关问题
1、SDS是什么?
2、为什么redis要用SDS实现
3、embstr 和 raw 的区别
4、什么时候转化? 会还原吗?