一:数据结构
到目前为止,redis共支持8种数据类型,除了5中常用的数据类Strings,Lists, Sets,Hashes,Sorted Sets。后续版本还支持了Bitmaps(基于String数据类型),Streams(像一个仅可追加的日志),geospatial indexes(以图为基础的数据类型,可用于记录二维坐标点,并支持查找附近的点)。
参考:https://redis.io/docs/manual/data-types/#bitmaps-and-hyperloglogs
二:高可用(哨兵模式的高可用)
实现方式:
2.1:主从复制数据
2.2:哨兵监控数据节点状态,一旦发现主节点不可用,选举丛节点作为主节点继续提供数据。
三:哨兵机制
- redis使用一组哨兵(sentinel)节点来监控主从redis服务的可用性。
- 一旦发现redis主节点失效,将选举出一个哨兵节点作为领导者(leader)。
- 哨兵领导者再从剩余的从redis节点中选出一个redis节点作为新的主redis节点对外服务。
四:最小配置实践:
以下我们以一主二从三哨兵的架构来搭建一个哨兵系统
步骤一:设置一主二从3个数据节点
找到 redis.conf
文件复制三份分别命名为 redis-master.conf
redis-slave1.conf
redis-slave2.conf 分别作为一个主节点和两个从节点的配置
步骤二:配置数据节点如下
#redis-master.conf master配置
port 6379
daemonize yes
logfile "6379.log"
dbfilename "dump-6379.rdb"
#redis-slave1.conf slave1配置
port 6380
daemonize yes
logfile "6380.log"
dbfilename "dump-6380.rdb"
slaveof 127.0.0.1 6379
#redis-slave2.conf slave2配置
port 6381
daemonize yes
logfile "6381.log"
dbfilename "dump-6381.rdb"
slaveof 127.0.0.1 6379
步骤三:设置哨兵配置文件
复制redis-sentinel.conf文件3份,分别为redis-sentinel-1.conf,redis-sentinel-2.conf,redis-sentinel-3.conf。并修改配置如下
# redis-sentinel-1.conf
port 26379
daemonize yes
logfile "26379.log"
sentinel monitor mymaster 127.0.0.1 6379 2
# redis-sentinel-2.conf
port 26380
daemonize yes
logfile "26380.log"
sentinel monitor mymaster 127.0.0.1 6379 2
# redis-sentinel-3.conf
port 26381
daemonize yes
logfile "26381.log"
sentinel monitor mymaster 127.0.0.1 6379 2
备注1:sentinel monitor
备注2:其他参数命令 sentinel <option_name> <master_name> <option_value>
sentinel down-after-milliseconds mymaster 60000 //失联6秒后认为mymaster发生了错误
sentinel failover-timeout mymaster 180000 //
sentinel parallel-syncs mymaster 1 //失败转移后,从节点并发复制新节点数据的数量(数据越小错误转移的完成时间就越长)
步骤四:启动数据节点,和哨兵节点
4.1:启动数据节点
redis-server redis-master.conf
redis-server redis-slave1.conf
redis-server redis-slave2.conf
4.2:启动哨兵节点
redis-server redis-sentinel-1.conf --sentinel
redis-server redis-sentinel-2.conf --sentinel
redis-server redis-sentinel-3.conf --sentinel
五:最小实践优化:
当M1主节点错误转移至M2如下图,客户端C1还持有着M1(又恢复了)的链接,并写入了M1节点的数据。此数据会丢失(因为M1已不是主节点下次同步数据就会被覆盖)。
+----+
| M1 |
| S1 |
+----+
|
+----+ | +----+
| R2 |----+----| R3 |
| S2 | | S3 |
+----+ +----+
--------------------------------------------------------------------
+----+
| M1 |
| S1 | <- C1 (writes will be lost)
+----+
|
/
/
+------+ | +----+
| [M2] |----+----| R3 |
| S2 | | S3 |
+------+ +----+
Configuration: quorum = 2
减缓(窗口期的数据还是会丢失)如上场景可通过配置节点的写入操作实现
min-replicas-to-write 1 //当复制节点小于1时,阻止该节点的写入权限
min-replicas-max-lag 10 //最后接受到ping命令的时间小于10秒,
六:集群方案
Redis 集群使用数据分片来实现, 一个 Redis 集群包含 16384 个哈希槽(hash slot), 数据库中的每个键都属于这 16384 个哈希槽的其中一个, 集群使用公式 CRC16(key) % 16384 来计算键 key 属于哪个槽。集群中的每个节点负责处理一部分哈希槽。
步骤一:为集群设置6个实例
复制6份redis.conf文件,并分别命名node_7000.conf, node_7001.conf , ......, node_7005.conf。并修改内容
# 后台执行
daemonize yes
# 端口号
port 7000
# 为每一个集群节点指定一个 pid_file
pidfile ~/Desktop/redis-cluster/redis_7000.pid
# 启动集群模式
cluster-enabled yes
# 每一个集群节点都有一个配置文件,这个文件是不能手动编辑的。确保每一个集群节点的配置文件不通
cluster-config-file nodes-7000.conf
# 集群节点的超时时间,单位:ms,超时后集群会认为该节点失败
cluster-node-timeout 5000
# 最后将 appendonly 改成 yes(AOF 持久化)
appendonly yes
步骤二:启动个个实例
redis-server redis_7000.conf
redis-server redis_7001.conf
redis-server redis_7002.conf
redis-server redis_7003.conf
redis-server redis_7004.conf
redis-server redis_7005.conf
备注:此时每个实例还不是集群模式
步骤三:启动集群模式
redis-cli --cluster create --cluster-replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
备注:--replicas 1
的意思是:为集群中的每个主节点创建一个从节点。
参考资料:
1.https://redis.io/docs/manual/sentinel/
2.https://zhuanlan.zhihu.com/p/112899242
七:驱除策略(Eviction policies)
当redis的内存到达maxmemory的设置值时就会使用maxmemory-policy指定的策略进行驱除数据,或者返回内存错误
可用的策略有一下
- noeviction: 当达到内存上线时,不驱逐,新数据不会被保存。
- allkeys-lru: least recently used (LRU)把最后使用的数据
- allkeys-lfu: least frequently used (LFU)最不频繁使用的数据
- volatile-lru: LRU+带有过期属性的数据.
- volatile-lfu: LFU+带有过期属性的数据.
- allkeys-random: 随机
- volatile-random: 随机+带有过期属性的数据.
- volatile-ttl: LFU++带有过期属性的数据+快过去的数据
备注1:当没有带有过期属性的数据时volatile-lru, volatile-lfu, volatile-random, 和 volatile-ttl策略就和 noeviction车略一样
备注2:配置参数maxmemory-samples 5 表明取5个实例作为LRU算法的驱除数据源