7000字 Redis 超详细总结笔记总
Redis 简介
Redis 支持数据持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
Redis 不仅仅支持简单的 key - value 类型的数据,同时还提供 list,set,zset,hash 等数据结构的存储
Redis 支持数据的备份,即 master - slave 模式的数据备份
Redis 优势
性能极高 – Redis 读的速度是 110000 次 /s, 写的速度是 81000 次 /s 。
丰富的数据类型 - Redis 支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
原子性 - Redis 的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过 MULTI 和 EXEC 指令包起来。
其他特性 - Redis 还支持 publish/subscribe 通知,key 过期等特性。
Redis 数据类型
OK
127.0.0.1:6379> get hello
'world'
sub-key2 : value2、sub-key3 : value3 这三个键值对
127.0.0.1:6379> hset hash-key sub-key1 value1
(integer) 1
127.0.0.1:6379> hset hash-key sub-key2 value2
(integer) 1
127.0.0.1:6379> hset hash-key sub-key3 value3
(integer) 1
// 获取 hash-key 这个 hash 里面的所有键值对
127.0.0.1:6379> hgetall hash-key
1) 'sub-key1'
2) 'value1'
3) 'sub-key2'
4) 'value2'
5) 'sub-key3'
6) 'value3'
// 删除 hash-key 这个 hash 里面的 sub-key2 键值对
127.0.0.1:6379> hdel hash-key sub-key2
(integer) 1
127.0.0.1:6379> hget hash-key sub-key2
(nil)
127.0.0.1:6379> hget hash-key sub-key1
'value1'
127.0.0.1:6379> hgetall hash-key
1) 'sub-key1'
2) 'value1'
3) 'sub-key3'
4) 'value3'
(integer) 1
127.0.0.1:6379> rpush list-key v2
(integer) 2
127.0.0.1:6379> rpush list-key v1
(integer) 3
127.0.0.1:6379> lrange list-key 0 -1
1) 'v1'
2) 'v2'
3) 'v1'
127.0.0.1:6379> lindex list-key 1
'v2'
127.0.0.1:6379> lpop list
(nil)
127.0.0.1:6379> lpop list-key
'v1'
127.0.0.1:6379> lrange list-key 0 -1
1) 'v2'
2) 'v1'
(integer) 1
127.0.0.1:6379> sadd k1 v2
(integer) 1
127.0.0.1:6379> sadd k1 v3
(integer) 1
127.0.0.1:6379> sadd k1 v1
(integer) 0
127.0.0.1:6379> smembers k1
1) 'v3'
2) 'v2'
3) 'v1'
127.0.0.1:6379>
127.0.0.1:6379> sismember k1 k4
(integer) 0
127.0.0.1:6379> sismember k1 v1
(integer) 1
127.0.0.1:6379> srem k1 v2
(integer) 1
127.0.0.1:6379> srem k1 v2
(integer) 0
127.0.0.1:6379> smembers k1
1) 'v3'
2) 'v1'
(integer) 1
127.0.0.1:6379> zadd zset-key 982 member0
(integer) 1
127.0.0.1:6379> zadd zset-key 982 member0
(integer) 0
127.0.0.1:6379> zrange zset-key 0 -1 withscores
1) 'member1'
2) '728'
3) 'member0'
4) '982'
127.0.0.1:6379> zrangebyscore zset-key 0 800 withscores
1) 'member1'
2) '728'
127.0.0.1:6379> zrem zset-key member1
(integer) 1
127.0.0.1:6379> zrem zset-key member1
(integer) 0
127.0.0.1:6379> zrange zset-key 0 -1 withscores
1) 'member0'
2) '982'
发布订阅
Reading messages... (press Ctrl-C to quit)
1) 'subscribe'
2) 'redisChat'
(integer) 1
127.0.0.1:6379> PUBLISH redisChat 'hello world'
(integer) 1
# 订阅者的客户端显示如下
1) 'message'
2) 'redisChat'
3) 'send message'
1) 'message'
2) 'redisChat'
3) 'hello world'
事务
批量操作在发送 EXEC 命令前被放入队列缓存。
收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余命令依然被执行。也就是说 Redis 事务不保证原子性。
在事务执行过程中,其他客户端提交的命令请求不会插入到事务执行命令序列中。
开始事务。
命令入队。
执行事务。
OK
redis 127.0.0.1:6379> SET book-name 'Mastering C++ in 21 days'
QUEUED
redis 127.0.0.1:6379> GET book-name
QUEUED
redis 127.0.0.1:6379> SADD tag 'C++' 'Programming' 'Mastering Series'
QUEUED
redis 127.0.0.1:6379> SMEMBERS tag
QUEUED
redis 127.0.0.1:6379> EXEC
1) OK
2) 'Mastering C++ in 21 days'
3) (integer) 3
4) 1) 'Mastering Series'
2) 'C++'
3) 'Programming'
这是官网上的说明 From redis docs on transactions: It's important to note that even when a command fails, all the other commands in the queue are processed – Redis will not stop the processing of commands.
OK
redis 127.0.0.1:7000> set a aaa
QUEUED
redis 127.0.0.1:7000> set b bbb
QUEUED
redis 127.0.0.1:7000> set c ccc
QUEUED
redis 127.0.0.1:7000> exec
1) OK
2) OK
3) OK
持久化
always 选项会严重减低服务器的性能
everysec 选项比较合适,可以保证系统崩溃时只会丢失一秒左右的数据,并且 Redis 每秒执行一次同步对服务器几乎没有任何影响。
no 选项并不能给服务器性能带来多大的提升,而且会增加系统崩溃时数据丢失的数量。
复制
主服务器创建快照文件,即 RDB 文件,发送给从服务器,并在发送期间使用缓冲区记录执行的写命令。
快照文件发送完毕之后,开始像从服务器发送存储在缓冲区的写命令。
从服务器丢弃所有旧数据,载入主服务器发来的快照文件,之后从服务器开始接受主服务器发来的写命令。
主服务器每执行一次写命令,就向从服务器发送相同的写命令。
哨兵
分片
最简单的是范围分片,例如用户 id 从 0 ~ 1000 的存储到实例 R0 中,用户 id 从 1001 ~ 2000 的存储到实例 R1中,等等。但是这样需要维护一张映射范围表,维护操作代价高。
还有一种是哈希分片。使用 CRC32 哈希函数将键转换为一个数字,再对实例数量求模就能知道存储的实例。
客户端分片:客户端使用一致性哈希等算法决定应当分布到哪个节点。
代理分片:将客户端的请求发送到代理上,由代理转发到正确的节点上。
服务器分片:Redis Cluster。