Redis系列---常见问题
目录标题
- key过期时间被刷新
- key过期会被立即删除吗
- mysql任何时候都比redis慢吗
- redis为啥是长连接
- 什么时候用redis
- 过期时间怎么设置
- 找出并删除亿级指定前缀的key
key过期时间被刷新
今天在开发的过程中遇到了一个Redis的问题: 当你在redis中插入一个key值,并且设置了对应过期时间. 当过期时间还没到的时候更新key值会导致过期时间被刷新, 针对这个问题: 我查看了下redis的官方文档, 他们是这么解释的:
The timeout will only be cleared by commands that delete or overwrite the contents of the key, including DEL, SET, GETSET and all the *STORE commands. This means that all the operations that conceptually alter the value stored at the key without replacing it with a new one will leave the timeout untouched. For instance, incrementing the value of a key with INCR, pushing a new value into a list with LPUSH, or altering the field value of a hash with HSET are all operations that will leave the timeout untouched.
翻译如下:
超时只能通过删除或覆盖键内容的命令清除,包括DEL、SET、GETSET和所有*存储命令。这意味着所有从概念上改变存储在键上的值而不用新键替换它的操作都将保留超时。例如,使用INCR增加键的值,使用LPUSH将新值推入列表,或者使用HSET更改散列的字段值,这些都是不保留超时的操作。
也就是,对redis中存在的key进行set或getset会将原来的key进行覆盖,并且是全部属性都覆盖。怀疑set方法时redis内部的操作就是先删除再存储。
key过期会被立即删除吗
这个涉及到redis的删除机制:Redis里面如果有大量的key,怎样才能高效的找出过期的key并将其删除呢,难道是遍历每一个key吗?假如同一时期过期的key非常多,Redis会不会因为一直处理过期事件,而导致读写指令的卡顿。
这里说明一下,Redis是单线程的,所以一些耗时的操作会导致Redis卡顿,比如当Redis数据量特别大的时候,使用keys * 命令列出所有的key。
因此Redis默认使用懒惰删除+定期删除相结合的方式处理过期的key。
- 懒惰删除:请求过期key时,若该key已过期且未删除则会删除;
- 定期删除:轮循进程,该进程轮循查找过期key进行删除
所以,不会立即删除,因为删除key时肯定是主服务来删除(因为redis是单线程的),所以当他在执行删除指令的时候,他就无法进行其他的操作,立即删除会影响性能;所以呢,他不会立即进行删除;
但是,如果一个key过期之后,无论redis删没删掉这个key外界都是查不到的;只是占用内存与否的问题。
mysql任何时候都比redis慢吗
mysql的读写效率没有想象的那么慢,mysql自己是有缓存的,mysql在不联表查取少量数据的情况下,基本与redis没什么差别。
redis为啥是长连接
为什么不建议使用mysql长连接,而却允许redis长连接:是因为redis使用的是IO复用模型,单线程可以同时处理多个连接,而mysql开源版一个线程对应一个连接。
什么时候用redis
- 热点数据
- 临时数据
- 复杂计算结果
Redis:作为一个内存数据库,Redis 具有非常高的读写并发能力,能够处理数十万到数百万的请求每秒。
MySQL:作为一个传统的关系型数据库,MySQL 的并发处理能力相对较低,通常在数千到数万的请求每秒。
不过提升核数并不会提升redis的并发能力i,因为一个redis 只能占用一核cpu。redis的并发量远比mysql要大,因为它没有io操作。
过期时间怎么设置
redis的key极少极少需要设置永不过期,如果一个key要设置永不过期,需要斟酌再斟酌。
找出并删除亿级指定前缀的key
由于Redis的单线程服务模式,命令keys *会阻塞正常的业务请求,不建议使用keys * pattern的方法进行查询,可能会使服务器卡顿而出现事故。如何获取指定的 key?
可以采用Redis提供的SCAN命令。SCAN 命令是一个基于游标的迭代器(cursor based iterator):SCAN 命令每次被调用之后都会向用户返回一个新的游标, 用户在下次迭代时会使用这个新游标作为 SCAN 命令的游标参数, 以此来延续之前的迭代过程。当 SCAN 命令的游标参数被设置为 0 时, 服务器将开始一次新的迭代;而当服务器向用户返回值为 0 的游标时, 表示迭代已结束。