redis是什么
redis是一个开源的、使用C语言编写的、支持网络交互的、可基于内存也可持久化的Key-Value数据库。
数据结构
- 字符串(strings)
set、get、incr、decr
incr、decr具有原子操作的特性,可用来进行统计计数 - 列表(lists)
lpush、rpush、lrange
底层实现是链表,插入删除快,但索引慢,常用来做消息队列;lrange可用来分页 - 集合(sets)
sadd、smembers、sismember、sunion
元素无序 - 有序集合(sorted sets)
zadd、zrange
元素有序 - 哈希(hashes)
存放的是键值对
持久化
- RDB(Redis DataBase)
在不同的时间点,将redis存储的数据生成快照并存储到磁盘等介质上。 - AOF(Append Only File)
将redis执行过的所有写指令记录下来,在下次redis重新启动时,只要把这些写指令从前到后再重复执行一遍,就可以实现数据恢复了。
redis重启时优先选择AOF方式,因数据恢复的完整度更高。
重写前,redis会创建一个“重写子进程”,将现有AOF文件指令进行压缩,并写入临时文件中。而主工作进程会将新指令存入缓冲区,等子进行就绪,会通知主进程将指令追加到AOF文件中
特点:指令合并,减小AOF文件大小;
主从
一般关闭主服务器的持久化功能,只让从服务器进行持久化,这样可以提高主服务器的处理性能。
从服务器通常被设置为只读模式。
事务
- MULTI用来组装一个事务
- EXEC用来执行一个事务
- DISCARD用来取消一个事务
- WATCH用来监视一些key,一旦这些key在事务执行之前被改变,则取消事务的执行
分布式锁
SETNX key value
将 key 的值设为 value,当且仅当 key 不存在。
若给定的 key 已经存在,则 SETNX 不做任何动作。
SETNX 是SET if Not eXists的简写
进程P4执行 SETNX lock.foo 以尝试获取锁
由于进程P1已获得了锁,所以P4执行 SETNX lock.foo 返回0,即获取锁失败
P4执行 GET lock.foo 来检测锁是否已超时,如果没超时,则等待一段时间,再次检测
如果P4检测到锁已超时,即当前的时间大于键 lock.foo 的值,P4会执行以下操作
GETSET lock.foo ‘<’current Unix timestamp + lock timeout + 1>
由于 GETSET 操作在设置键的值的同时,还会返回键的旧值,通过比较键 lock.foo 的旧值是否小于当前时间,可以判断进程是否已获得锁
假如另一个进程P5也检测到锁已超时,并在P4之前执行了 GETSET 操作,那么P4的 GETSET 操作返回的是一个大于当前时间的时间戳,这样P4就不会获得锁而继续等待。注意到,即使P4接下来将键 lock.foo 的值设置了比P5设置的更大的值也没影响。
另外,值得注意的是,在进程释放锁,即执行 DEL lock.foo 操作前,需要先判断锁是否已超时。如果锁已超时,那么锁可能已由其他进程获得,这时直接执行 DEL lock.foo 操作会导致把其他进程已获得的锁释放掉。