reids
Redis命令
字符串
1、字符串自增自减
2、对字符串的一部分内容进行读写
3、对字符串提供二进制操作
4、主要做一些**复杂计数**功能的缓存
列表
1、列表数据的推入和弹出
2、将元素从一个列表移动到另一个列表,(元素移动)
3、阻塞执行命令的客户端直到其他元素给列表添加记录为止。(阻塞弹出)
4、可以做一些**简单的消息队列**的场景
集合(set)
1、插入、移除、移动
2、多个集合求交集、并集、差集运算
3、主要做**全局去重**等功能
散列(hash)
1、添加、删除键值对、获取所有键值对
2、对键值对的值进行自增或自建操作
3、主要做**存储结构化**的对象
有序集合(sorted set)
1、有序集合添加、更新已有元素
2、有序集合进行交集、并集运算
3、范围型数据获取命令、范围型数据删除命令
4、主要做**取TOP N、延时任务、范围查找**
发布与订阅
1、subscribe 订阅给定的一个或多个频道
2、unsubscribe 退订一个或多个频道
3、publish 向给定频道发送消息
4、psubscribe 订阅与给定模式相匹配的所有频道
5、punsubscribe 退订给定的模式,没有给定模式,就退订所有模式。
其他命令
1、sort 排序(alpha,by,get) 对列表、集合、有序集合进行排序,可将散列存储的数据作为权重进行排序,以及怎样获取并返回散列存储的数据。
2、redis 事务
Redis的基本事务(basictransaction)需要用到MULTI命令和EXEC命令,这种事务可以让一个客户
在不被其他客户端打断的情况下执行多个命令。和关系数据库那种可以在执行的过程中进行回滚
(rollback)的事务不同,在Redis里面,被MULTI命令和EXEC命令包围的所有命令会一个接一个地执
行,直到所有命令都执行完毕为止。当一个事务执行完毕之后,Redis才会处理其他客户端的命令。
3、键的过期时间:键过期,redis会自动删除该键
persist: 移除键的过期时间
ttl: 查看给定键距离过期还有多少秒
expire: 让给定的键在指定的秒数之后过期
expirear: 将给定键的过期时间设置为给定的时间戳
pttl:查看给定键距离过期时间还有多少毫秒
pexpire:让给定键在指定的毫秒数之后过期
pexpireat:将一个毫秒级精度的时间戳设置为给定键的过期时间
数据安全与性能
持久化
1、快照
save 60 10000 多久执行一次自动快照操作
如果60秒有10000次写入,会自动触发bgsave命令
stop-writes-on-bgsave-error no :创建快照失败后是否仍然继续执行写命令
rdbcompression yes :是否对快照文件进行压缩
dbfilename dump.rdb :命名快照文件
快照持久化:
客户端发送命令:bgsave (创建子线程写入快照) 或 save (快照创建完毕之后不在接收客户端的消息)
redis 通过shutdown 命令或标准 term信号时,会执行save
2、只追加文件(AOF)
appendfilename “appendonly.aof”
appendonly yes:是否使用AOF持久化
appendfsync ererysec 文件同步频率(always ereryssec no)
为了解决aof文件体积不断增大,用户可向redis 发送bgrewriteaof 命令,这个命令会通过移除AOF文件中的冗余命令来重写AOF文件。
no-appendfsync-on-rewrite no
执行bgrewriteaof操作和主进程写aof文件的操作,两者都会操作磁盘,而bgrewriteaof往往会涉及大量磁盘操作,
这样就会造成主进程在写aof文件的时候出现阻塞的情形,如果应用系统无法忍受延迟,而可以容忍少量的数据丢失,则设置为yes。如果应用系统无法忍受数据丢失,则设置为no。
auto-aof-rewrite-percentage 100 (100%)
auto-aof-rewrite-min-size 64mb
自动触发bgrewriteaof 的设置,AOF文件的体积大于64MB且AOF文件的体积比上一次重写之后的体积大了至少一倍。
Redis会记录上次重写时的AOF文件大小,默认配置时当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发
3、dir ./ 持久化保存位置
复制(replication)
配置及启动过程
(设置主从服务器)
复制可以让其他服务器拥有一个不断地更新的数据副本,从而使得拥有数据副本的服务器可以用于处理客户端发送的读请求。
1、配置
方式一、
开启从服务器所必须的选项只有slaveof一个。如果用户在启动Redis服务器的时候,指定了一个
包含 slaveof host port 选项的配置文件,那么Redis服务器将根据该选项给定的IP地址和端口号来连
接主服务器。
方式二、
通过发送SLAVEOF host port命令来让服务器开始复制一个新的主服务器
用户可以通过发送SLAVEOF no one命令来让服务器终止复制操作,不再接受主服务器的数据更新;
从服务器在进行同步时,会清空自己的所有数据。
Redis的sentinel(sentinel集群)提供了一套多daemon间的交互机制,解决故障发现,failover(故障转移)决策协商机制的问题
主从链
从服务器也可以有自己的从服务器,从而形成了主从链。
从服务器对从服务器进行复制在操作上和从服务器对主服务器进行复制的唯一区别在于,如果从服务器X拥有从服务器Y,那么当从服务器X在执行表4-2中的步骤4时,它将断开与从服务器Y的连接,导致从服务器Y需要重新连接并重新同步(resync)。
INFO命令提供了大量的与redis服务器当前状态有关的信息。
检查硬盘写入
1、通过redis-check-aof 和redis-check-dump 检查AOF文件和快照文件的状态。
2、更换主服务器
1、从服务器B 执行save命令,创建一个新的快照 >>> 使用OUIT退出客户端
2、将快照发送到新的服务器C上 >>> 启动新的服务器C
3、将从服务器B 成为新的服务器C的从服务器
Redis事务
1、MULTL开始事务 >>>> 用户传入多个命令
2、EXEC 结束。(EXEC命令被调用之前,不会执行任何实际性修改)
延迟执行有助于提升性能。
3、WATCH命令对键进行监视,(如果有其他客户端对任何被监视的键进行了替换、更新、删除操作,用户尝试执行EXEC命令时,事务将失败,并返回一个错误)。
4、DISCARD
1、UNWATCH命令可以在WATCH命令执行之后、MULTI命令执行之前对连接进行重置(reset);
2、DISCARD命令也可以在MULTI命令执行之后、EXEC命令执行之前对连接进行重置。
用户在使用WATCH监视一个或多个键,接着使用MULTI开始一个新的事务,并将多个命令入队到事务队列之后,
仍然可以通过发送DISCARD命令来取消WATCH命令并清空所有已入队命令。
使用非事务性流水线(pipeline)
性能上的注意事项
1、redis-benchmark :常用的redis命令1秒内能执行的次数,默认使用50个客户端测试
参数 等
-c 1 :使用一个客户端测试
-q :简化输出结果
面试点
redis为什么这么快?
- 纯内存操作
- 单线程操作,避免了频繁的上下午切换
- 采用了非阻塞I/O多路复用机制
- 我们的redis-client在操作的时候,会产生具有不同事件类型的socket。在服务端,有一段I/0多路复用程序,将其置入队列之中。然后,文件事件分派器,依次去队列中取,转发到不同的事件处理器中。 需要说明的是,这个I/O多路复用机制,redis还提供了select、epoll、evport、kqueue等多路复用函数库。
redis 的过期策略和内存淘汰机制
- 定期删除+惰性删除,但这可能导致一些从未访问过的key不会得到删除,所以redis配置内存淘汰机制
- (定期删除)每隔一段时间(100ms), 随机进行抽查,如果过期,则进行删除;
- (惰性删除),每次获取key的时候,会进行查看key是否过期,过期则进行删除;
- 内存淘汰机制 # maxmemory-policy volatile-lru
- noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。
- llkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。推荐使用,目前项目在用这种。
- allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。
- volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。这种情况一般是把redis既当缓存,又做持久化存储的时候才用。
- volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。
- volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。
缓存穿透、缓存雪崩、缓存击穿
- 缓存穿透:访问一个不存在的key,缓存不起作用,请求会穿透到DB,流量大时DB会挂掉。
- 采用布隆过滤器,使用一个足够大的bitmap,用于存储可能访问的key,不存在的key直接被过滤;(转)布隆过滤器
- 访问key未在DB查询到值,也将空值写进缓存,但可以设置较短过期时间。
- 缓存雪崩: 大量的key设置了相同的过期时间,导致在缓存在同一时刻全部失效,造成瞬时DB请求量大、压力骤增,引起雪
崩。- 可以给缓存设置过期时间时加上一个随机值时间,使得每个key的过期时间分布开来,不会集中在同一时刻失
效; - 采用限流算法,限制流量;
- 采用分布式锁,加锁访问。
- 可以给缓存设置过期时间时加上一个随机值时间,使得每个key的过期时间分布开来,不会集中在同一时刻失
- 缓存击穿: 某一个热点 key,在缓存过期的一瞬间,同时有大量的请求打进来,由于此时缓存过期了,所以请求最终都会DB,造成瞬时数据库请求量大、压力骤增,甚至可能打垮DB
- 互斥锁
- 热点数据不过期
public Object getData(String key) throws InterruptedException {
Object value = redis.get(key);
// 缓存值过期
if (value == null) {
// lockRedis:专门用于加锁的redis;
// "empty":加锁的值随便设置都可以
if (lockRedis.set(key, "empty", "PX", lockExpire, "NX")) {
try {
// 查询数据库,并写到缓存,让其他线程可以直接走缓存
value = getDataFromDb(key);
redis.set(key, value, "PX", expire);
} catch (Exception e) {
// 异常处理
} finally {
// 释放锁
lockRedis.delete(key);
}
} else {
// sleep50ms后,进行重试
Thread.sleep(50);
return getData(key);
}
}
return value;
}
reids 分布式锁
setnx实现分布式锁
- 命令:SET key value [EX seconds|PX milliseconds] [NX|XX] [KEEPTTL]
- EX:键的过期事件设置为秒,PX:键的过期事件设为毫秒 ; 防止锁没释放,系统崩了之类的;
- NX: 键不存在时,才对键进行设置操作, 等同于setnx key value; XX:只有键已经存在时,才对键进行设置操作;
- TTL:生存时间,保证存活的生存时间;
- value 为拿到锁的应用端ID,防止 不是拿到锁的线程解锁
- get / del 操作非原子操作,索引删除锁一般使用lua脚本,通过redis的eval/evalsha命令来运行