Redis Cluster

本文基于 Redis 5.0.5

首先安装 Redis

wget http://download.redis.io/releases/redis-5.0.5.tar.gz

tar xzf redis-5.0.5.tar.gz

cd redis-5.0.5/

sudo make && make install

修改配置文件 redis.conf

# 同一台机器上,每个 Redis 实例的端口要不一样
port 7000

# 开启实例的集群模式
cluster-enabled yes

# 保存节点配置文件的路径
cluster-config-file nodes.conf

# 节点间通信的超时时间
cluster-node-timeout 5000

# 采用 AOF 
appendonly yes

拷贝并配置集群实例

cd ..
mkdir -p redis-cluster/{7000,7001,7002,7003,7004,7005}

把 redis.conf 拷贝到上面建立的数字目录下,修改相应的端口号为目录名。

继续阅读

基于Redis实现分布式锁

用单实例的正确实现

命令:set resource_name my_random_value NX PX timeout_millis,在 key resource_name 不存在时(NX选项的作用)设置这个key 的值为 my_random_value、超时时间设为 timeout_millisPX选项的作用)。

删除key的时候用 Lua 脚本来检测key的值是否为 my_random_value,是才允许删除;需要保证这个值在所有客户端里唯一;(借助 Lua 实现一个 CAS 操作)

一些注意点与问题

  • 一个分布式锁必须设置超时时间,否则一旦某个客户端获取锁成功后与 Redis 无法通信,那么它会一直持有这个锁,其他客户端无法获得锁。
    这个过期时间叫做锁的有效时间(lock validity time),客户端必须在这个时间内完成对资源的访问操作。

  • 设置key与超时时间必须在一个命令里完成。如果客户端在设置了key后、设置超时时间前崩溃,那么它会一直持有这个锁。

  • 释放锁时必须检查key对应的值是否与自己持有的一致(通过 Lua 实现CAS),防止误删其他客户端持有的锁。防止出现:客户端A准备释放持有的锁时,检测到值与自己持有的一致,然后由于某种原因被长时间阻塞,锁的超时时间到达后客户端B获取了锁,此时客户端A执行不检查key值的删除操作就会破坏了锁。

继续阅读

Redis-RDB-Dump-File-Format 中文翻译

今年年初翻译的,都忘得差不多了,最近想用Go写个程序解析RDB文件,重新翻出来。

翻译自:
https://github.com/sripathikrishnan/redis-rdb-tools/wiki/Redis-RDB-Dump-File-Format

如果对本文档的后续更新有兴趣,可关注:https://github.com/wen866595/open-doc

Redis RDB 文件格式

Redis *.rdb 文件是一个内存内存储的二进制表示法。这个二进制文件足以完全恢复Redis的状态。

rdb文件格式为快速读和写优化。LZF压缩可以用来减少文件大小。通常,对象前面有它们的长度,
这样,在读取对象之前,你可以准确地分配内存大小。

为快速读/写优化意味着磁盘上的格式应该尽可能接近于在内存里的表示法。这种方式正是rdb文件采用的。
导致的结果是,在不了解Redis在内存里表示数据的数据结构的情况下,你没法解析rdb文件。

解析RDB的高层算法

在高层层面看,RDB文件有下面的格式:


----------------------------# RDB 是一个二进制文件。文件里没有新行或空格。
52 45 44 49 53              # 魔术字符串 "REDIS"
00 00 00 03                 # RDB 版本号,高位优先。在这种情况下,版本是 0003 = 3
----------------------------
FE 00                       # FE = code 指出数据库选择器. 数据库号 = 00
----------------------------# 键值对开始
FD $unsigned int            # FD 指出 "有效期限时间是秒为单位". 在这之后,读取4字节无符号整数作为有效期限时间。
$value-type                 # 1 字节标记指出值的类型 - set,map,sorted set 等。
$string-encoded-key         # 键,编码为一个redis字符串。
$encoded-value              # 值,编码取决于 $value-type.
----------------------------
FC $unsigned long           # FC 指出 "有效期限时间是豪秒为单位". 在这之后,读取8字节无符号长整数作为有效期限时间。
$value-type                 # 1 字节标记指出值的类型 - set,map,sorted set 等。
$string-encoded-key         # 键,编码为一个redis字符串。
$encoded-value              # 值,编码取决于 $value-type.
----------------------------
$value-type                 # 这个键值对没有有效期限。$value_type 保证 != to FD, FC, FE and FF
$string-encoded-key
$encoded-value
----------------------------
FE $length-encoding         # 前一个数据库结束,下一个数据库开始。数据库号用长度编码读取。
----------------------------
...                         # 这个数据库的键值对,另外的数据库。
FF                          ## RDB 文件结束指示器
8 byte checksum             ## 整个文件的 CRC 32 校验和。

继续阅读