Professional Documents
Culture Documents
20210519 Tair技术沟通及最佳实践 bixin
20210519 Tair技术沟通及最佳实践 bixin
20210519 Tair技术沟通及最佳实践 bixin
- Tair的体系和能力 - 场景讨论:选型
- 云原生 & 软件化 - 场景讨论:proxy的使用
- 场景讨论:容灾和一致性
• 大规模商用的坑比较多
- 持久化,主备同步,LRU淘汰,单线程判活,切换,备份,大容量稳定性都有问题
- 应用场景复杂;基础组件不全,缺少监控
- 运维架构不完整;资源隔离性差;扩容不平滑
• Redis正在商业化中
- 2020/07 正式交由Redis Labs商业化运作;逐步拉开“社区”-“企业版”距离
- 阿里云:对社区Redis贡献最大的组织:Core Member 1(of 5), Cert Contributor 1 (of 10),Jedis Reviewer 1 (of 3)
- 生态:Redis-shake,modules,apasaracache;团队:国内最大Redis社区PD;原Pika,swapdb作者等
1. 用户所有的来自不同client的请求,实际上在每个event到来
后,交由后端单线程执行。等每个event处理完成后,才处理下
一个
Redis Client ①S
ET k 2. 单线程run-to-completion 就是没有dispatcher,没有后端的
ey1 multi-worker
valu
e1
③ UN
LINK
Key3
使用Sentinel判活的trick:
• Ping命令判活:ping命令同样收到慢查询影响,如果引擎被卡住,则ping失败
• Duplex Failure:sentinel由于慢查询切备(备变主)再遇到慢查询Redis将出现OOS
SLOW
Redis Client
之所以使用连接池,是因为Redis协议不支持连接收敛
key1
e1
• Message没有ID,所以Request和Response对不起来
valu
ALL big
• 非常类似HTTP 1.x消息 Redis Client
K
key1
①O
② HGET
ET
①S
2. 如果用户返回的及时,那么连接池一直保有的连接数并不高
• 但是一旦返回不了,又有新的请求,就只能再checkout一根连接
1. 每次查询,都要先从连接池拿出一 • 当连接池被checkout完,就会爆没有连接的异常:
根连接来,当返回后,再放回连接池
"Could not get a resource from the pool"
Redis Client
- C10K的问题:引擎当挂住太多active链接的时候,性能下降太多。测试结果是当有10k active连接时,性能下降30-35%,由于
引擎端的挂住的链接不能被返回,用户大量报错
Read Write
Read Write
6.0 MIO:
• 折衷的改进
• 可以提升吞吐,但仍旧无法解决C10K问题
• 抗冲击性恶劣条件下更差(大量active link分发瓶颈)
• IO线程太多没有用,IO/Worker比例在3:1即可打满worker
Process
Tair Real-MIO:
• 最初为解决天猫淘宝等大连接数而设计:单IO挂10K链接
• 可以提升吞吐,极大提升抗冲击能力
• IO/Worker满载比例在4.5:1,但可提升IO线程数挂住更多worker
• O(1)命令性能可达3倍;但O(n)加速不明显,只有吞吐提升
• 完全兼容Redis所有命令
不小心设计出了bigkey,并且有range操作
很小心避免了bigkey和range,但是没想到还有其他用户在用
很小心避免了bigkey和range,也限制了别人;但是不小心用了开源工具下发了keys *
发客户端忘了回收连接池
业务流量突增,导致访问和流量大幅超出预期
Redis/Tair使用特点
• 基本工作在同步链路,一旦latency(rt)受影响,就会直接影响用户体验
• 使用方式特别多,摸不清楚边界。问题都是出在量上涨后(容量,访问量)
IP
SDK
Sentinel
GOSSIP
IP
Sentinel
IP SDK:
• 使用支持redis cluster模式的SDK
• 部分命令放弃兼容
Gossip:
• SDK层处理ASK/MOVE中间状态,做容错重定向
• 协商式集群,最终一致;用sentinel做高可用(HA)
• “业务无感知”的程度取决于引擎(Redis在MOVE bigkey会卡住)
• 用于协商路由,和传递PUBSUB
• 集群版最少3节点起
• 集群节点多(>32)形成广播风暴,收敛速度慢
核心问题 2: 集群化问题,和成本
VIP
CS Node
VIP SDK
Native Cluster Mode
CS Node CS Node
VIP
SDK:
Data Node: • 可使用Proxy模式,或者native-cluster模式(直连)
• 集群版1节点起跳 • Proxy模式高度兼容主备
• 高速收敛平均时间50ms,最差1s • HA不断链接(目前云盘版具备,本地盘版本7月上线)
• 无缝HA(目前云盘版具备,本地盘版本7月上线)
** 成本控制
• Redis/Tair的成本考虑
- Redis的footprint过高(aof-rewrite fork,bgsave fork),低售卖水位
- 共享资源的独占/隔离和高效动态调度;多副本的调度
- 特殊资源被忽视:存储和云盘,LVS vs. IPVS
- 特殊需求:Proxy,强数据安全
- 折旧和替换
- 安全,审计,恢复,洞察
• Orchestration
- 现代数据库的设计思路的变化
- Redis不具备Orchestration条件,得改内核
阿里云Redis企业版
多线程三倍性能
PITR
大链接稳定性
8种新数据结构(modules) 跨域多活 混合存储/冷存
400K热点抗量
Rich SDK CDC (TBD) 冷热互通
热点散列 (TBD)
企业级能力
TairSearch (TBD) 核心引擎 可调节一致性
NGLB/GPU Event Bus (TBD) 可靠存储 Memcache
模块
AEP/NVM Couchbase) KV (TBD)
SSL/白名单
RDMA网络 HA独立侦测
Aerospike KV (TBD)
TDE加密 (TBD)
新硬件 平滑变配 兼容力
账号体系
参数管理 代理/直连集群 数据分析
审计系统(读写)
监控系统 HA子系统 实时热点发现
安全子系统
日志系统 性能分析
Set Hash Zset
备份/恢复 List HLL CloudDBA子系统
GEO
告警 String
OAM子系统 PUBSUB
Streaming 存储核心
• 随业务增长的必然化需求
• 从业务安全(同城/跨域容灾)走向业务体验(跨域多活)
• 例:阿里2015年电商单元化需求
Simple Hard
同城容灾(Zone-Redundancy) 异地容灾(Geo-Redundancy)
多副本容灾
multi-replica
DNS切流
接入层 7层限流分流 接入层
RPC
业务层 无状态改造 业务层
NoSQL/缓存 多活
缓存层/高速存储 缓存层/高速存储
配置层 配置层
上海 北京
单元化核心技术难在底层数据同步,调度/mesh技术已经快速收敛,标准化
sync Write
Replication
方案1:
1. 远程挂载slave,远端以只读节点存在
Ins@Region1 2. 只能做容灾使用。如psync超出缓冲区,
则触发全量复制,此时远端业务受损
psync/psync2
op(2)
App@Region1 Master x Slave x1
psync/psync2
PSYNC协议:
Repl-buff
1. 断点续传能力非常弱;超出buff就会
触发全量同步
Ins@Region2
Syncer
2. 阿里改进:always-psync,用磁盘扩
大复制缓冲区。不能解决最差情况
Read only
方案2:
Slave x2’ Slave x2 App@Region2
1. 使用同步器,伪装成slave,命令发向远端
2. 只能做一次性数据导入。如触发全量复制则远程不 it
e
Wr
一致,如INCR/DECR,LPUSH等 ad
Slave y1 Master y Re
3. 不能做双向复制,不能区分用户写入和同步写入
Redis本身不支持跨距容灾或多活是因为PSYNC协议不支持稳定的复制流
Region:Shanghai
Message Queue:
App 1. 对于无binlog对meta等动态信息更新
server-SH-1
2. 订阅,生产和消费来更新远端高速存储
LB
App
server-SH-2 DTS
Load balancer
Msg Queue
DTS服务: App App App
server-BJ-1 server-BJ-2 server-BJ-3
1. 订阅DB的binlog,用户制定规则,删除本地缓存
2. 针对复杂数据格式,更新复杂,如果删除会导致命中率非常低
Region:Shenzhen
App DTS
server-SH-1
LB
App RDS
server-SH-2
Region:Beijing
App
server-SH-1 Load balancer
LB
App
server-SH-2
App App App
server-BJ-1 server-BJ-2 server-BJ-3
Tair全球多活:
1. Read/Write Everywhere
Region:Shenzhen 2. 高SLA保证
Region:Beijing
App
server-SH-1
LB
App
server-SH-2
Tair多活基于稳定的binlog协议,可提供高SLA的复制流
• Redis的问题基本都是规模化后产生的
• Redis/Tair工作在同步链路,抖动直接影响客户体验
• 设计哲学有问题:简单代码对复杂场景覆盖必然有问题
• 要从代码层面运维Redis,否则比较容易走入运维灾难
• 现代数据库要把数据内省能力,可集成能力与管控体系当成一等公民去建设
• 单元化 – 大家都想要,但最核心的是底层存储/数据库的同步/多活能力
• Tair:高性能NoSQL数据库系统
RDB2.0 图数据库
MDB Tair2.0
Tair1.0 LDB
PDB2.0
GDB
RDB - 阿里自研,双11等活动抗量的核心系统
产品演进 包含 孵化上云
- Redis/memcache/GDB是Tair上云产品
- 对内放弃部分兼容性,使用定制SDK
- 阿里全面上云:向云原生发展新3.0
孵化上云 产品演进/全面上云
• 企业级Redis - Tair
演进/共用
平台共用 功能反向移植 性能增强版(RDB3.0) - 性能增强版/混合存储版,全自研存储
容量存储版(PDB3.0)
持久内存版(PENA)
- 对内对外一套服务
云memcache 云Redis社区版 云Redis企业版(Tair3.0) - 完全兼容Redis语义及生态
- 与云Redis同架构,服务升级
云Redis 6.2
2021-07上线
EOS 已下线 2021 Q2 EOL TBD TBD
2022 Q2 EOS
Tair 持久内存(兼容6.0)
2021-07上线
EOS 已下线
Tair 容量存储
Entire Dataset
(TairDB on AEP)
混合存储SCM(Semi Hot)
Redis Protocol
Consolidating
pubsub pubsub
通知 pubsub pubsub
队列阻塞API ③ 队列阻塞API ③
数据功能
自定义函数 lua/script lua/script 无 lua/script
CAS/CAD
TairString
TairHash
TairDoc (兼容rejson) CAS/CAD CAS/CAD
Tair扩展模块 无 无
TairBloom (兼容rebloom) TairString TairString
TairGIS
TairCPC
TairTS
最终一致 最终一致
主备复制一致性 最终一致 最终一致 最终一致
主备强一致 (Coming soon:2021-07) 主备强一致 (TBD)
落盘模式
秒级持久化
落盘一致性 ④ 秒级持久化 命令级持久化 秒级持久化 秒级持久化
命令级持久化
TBD: To Be Done,代表未来有计划支持,具体发布时间暂无确定时程,视各功能优先级而定。
①:落盘型Tair的访问是一个区间,视用户的内存/磁盘使用比例(如全在内存,或磁盘),和访问模型(zipfan/uniform)而定,详细见产品的性能白皮书
②:string的bitmap接口包括:bitop,bitcount,bitpos,getbit,bitfield 等
③:阻塞性API包括:brpop,blpop,brpoplpush,bzpopmin,bzpopmax 等
④:数据落盘方式主要有写穿(write through)和写回(write back)写穿能力能够获得更好的命令及持久化,提供更高的数据可靠性
Tair性能增强型 Tair持久内存型 Tair容量存储型 Tair混合存储 阿里云Redis社区版
EOL,已经停止售卖 4.0/5.0/6.0/2.8
单位成本
2x 0.7x 0.15 ~ 0.3x 1x
规格 (与Redis社区版对比)
极高性能,极高抗压,更多数据结
高数据可靠与成本考虑,目标场景
构简化开发提高数据存储和处理性 高数据可靠和性能并存,目标场 中小型应用,验证型应用;
为高存储/低访问比,对数据持久化
选型指南 能,全球多活部署,数据闪回保障 景为高性能且成本作为次要考虑 已经下线 标准化redis使用和迁移;
要求高,成本作为第一考虑因素的
安全,目标场景为以性能为中心并 因素的数据缓存与存储场景 2.8版本已经EOL停止售卖
数据存储场景
对成本不敏感的缓存场景
TBD: To Be Done,代表未来有计划支持,具体发布时间暂无确定时程,视各功能优先级而定。
①:落盘型Tair的访问是一个区间,视用户的内存/磁盘使用比例(如全在内存,或磁盘),和访问模型(zipfan/uniform)而定,详细见产品的性能白皮书
⑤ : always-psync是redis psync协议的增强,在完全兼容psync协议同时能够做稳定的断点续传;只支持psync协议的社区版redis可能会在复制缓冲区失效后引发全量复制
⑥ : BYOK:Bring-Your-Own-Key,一种数据层存储加密的实现方式,目前是最常见和通用的高级加密方式
⑦ : Real Multi-IO:区别于Redis社区版6.0的多线程,Tair的Real MIO能够将IO加速进行的更彻底,具备更高的抗链接冲击性,并可以线性地提升吞吐
Private Cache(local cache)
关于cache 1.
2.
临近用户,性能好
Cache的失效和同步有问题
App1 cache
• 主要用于offload 数据源
Redis
App2 cache
DB
- 注意cache的容错性:可能脏,也可能丢
- 区分并存储高度变化的数据 App3 cache
- Cache的同步问题
- Redis的场景是shared-cache App App
① ② ⑤ ① ④
• Cache使用 Read Cache
1.2 读cache,如果读到返回
Write Cache
1 删cache(也可不删,有争议)
Redis Redis
3.4 如果读不到,则回源读, 2.3 写数据源
- 读cache ③ ④
更新cache(5)
② ③ 4 可以更新cache,如果有read cache则
可无此步骤
- 写cache
DB DB
• 怎么解决缓存系统的高可用性?(high availability)
• 缓存数据和数据源的存储比例是多少最合理?(hit ratio)
• 如果缓存里的数据批量失效,导致回源压力大,怎么办?(cache stampede)
• 我需要缓存和数据源强一致,要怎么做?(strong consistency)
• 缓存满了应该怎么办?(LRU,eviction策略等)
Cache的实质:通过就近存储(locality)提升性能的方法。
涉及数据的多份拷贝的生存周期,和数据一致性问题
- 国际定位为缓存 Input
buff
• 缓存 vs MMDB
Mgr
- 容错能力不同 User Dataset buff+mem
- 数据一致性要求不同 Output
buff
• Tair定位为内存数据库
Fake Lua
- 内存数据库 != 内存关系型数据库 JIT Link Lua JIT Mem
Overhead 1. Code cache
- 持久内存更多具备可靠内存数据库特性 2. 伪装成link
3. Lua执行缓存
- 长期演进,footprint control 4. 大lua的临时变量和存储
• 数据在存储介质的组织形式不同
- 内存:T-Tree,MassTree,Hash,SkipList等
- 磁盘:B-Tree及优化树,LSM等
- 持久内存: (暂不脱密)
• SCM(AEP/Optane)正在引发数据库设计革命
- 近似内存的访问能力,和持久化能力 大内存fork demo
You will know
- 抖动,恢复速度等工程难题得到很好的平衡
• Tair产生本质上是将阿里多年的企业级实践上云
• Redis是向前兼容的,升级没有兼容性问题
- 2.8和4.0甚至5.0已经没有社区服务,4.0将很快走入EOL
- Tair是长期维护版本,跨类型升级要检查
• 混合存储走向下一代
- 持久内存 + 容量存储
- 容量存储选型提醒(!)
• Tair后续会向内存数据库方向发展
- 重点在持久内存(AEP/SCM)
- 着力解决footprint的影响问题
Proxy Proxy
RW
Master Master RO RO RO
• 单副本对应缓存场景 Proxy
Proxy Proxy
- 一般关闭aof落盘,减少磁盘IO影响
- HA策略为空切,命中率丢失 1/N(分片数)
- 成本低,可用率高(不需复制数据)
- 数据最终一致
单
- 主挂切备,备挂换新备 Replica Replica
Master
• 多副本一般对应读写分离 空切示例:
命中率丢失25%
双
- 太多链式副本容灾收益低 Replica
- 开放部分只读备提升读能力 注:云Tair/Redis不支持锯齿型集群实例
多
34 All Rights Reserved © Tair 2018 - Alibaba Group 数据库产品事业部
云设施 – NGLB
VPC-A
App@ECS
• 传统负载均衡问题
Packets Packets
SLB
- 数据穿透,单个负载均衡集群能力有限
- 单个VIP的流量/CPS能力有限
- 负载过高需要进行迁移
App@ECS
- 使用高层交换机做side-car,首包过NGLB Followed Packets
- 数据直连,提供更高的带宽
- 降低fastpath网元依赖,降时延,稳定性提升 Initial Packet
- 适合超高吞吐/Tair使用场景 NGLB
1.0x
!
" 0.9x
• 对比总揽
1.0x
- 只有性能稍损(90% *)
!
# 1.4x - 售价只有内存版70%
• 兼容性
主备:1G~64G
$ 集群:2G~4T - 兼容6.0版本(除stream),向下兼容所有社区命令
% 主备:32G~256G
集群:64G~32T - 常用的TairString和CAS/CAD命令
• 企业级
可用性99.95%
& PRO>0,有fork抖动
- 真正的命令级别持久化(write-through)
' 可用性99.99%
PRO=0,无fork抖动 - 和增强性能一样的企业级架构能力
- SSL/TDE等企业级加密能力
基础版
(
) 命令级别落盘
全球多活,PITR,热点散列等
典型场景
Redis/Tair的最佳实践,和服务能力边界
Key-Value
• List的扩展用法 – Queue/Stack
- 类似STL的Vector,可以通过rpush/rpop/lpush/lpop来实现stack和queue
- List Streaming(feed系统)
• 场景讨论:
- 答题直播中每用户答题场景(答题活动)
- 更好的做法?String的BITMAP接口和海明距离
• 每个用户每轮答题,设置一个key,比如user1在第一轮答题的key是 round:1:user1
• 每答对一道题,设置相关的bit为1
- 比如user1答对了第5题,那么就设置第5个bit为1就可以了,如: SETBIT round:1:user1 5 1
- bitfield默认bit都是0,答错可以不设置
• 计算用户总共答对了几道题,就可以使用 BITCOUNT 命令统计1的bit个数
SETBIT round:1:user1 11 1
SETBIT round:1:user1 9 1
SETBIT round:1:user1 5 1
round:1:user1 1 1 1 1 1 FAIL
round:1:user2 1 1 1 1 1 1 1 1 1 1 1 1 PASS
• 特点: pkey-skey-value类型(KKV)
- key-value系统,可以被认为是一个“Global Remote HashMap”,Redis的String接口就是Key-Value接口
- Redis的Hash,可以认为是一个 “Named HashMap”,其名字就是hash的key
• Hash适合存放一个结构化数据(primary-key)具有多个属性(field/sub-key)
- Hash最合适用法是类似:一个XML/JSON/YAML多属性,类似一个数据库Table的一行
- 本质上是schema-less的,Redis不能做自动索引;业务自己做索引没有事务性
• Hash不适合:
- 存放同质且大量的key;类似列存,记录大量的列数据 à 导致数据倾斜,热点
- hmget/hgetall/hscan的大量range使用 à 导致slowquery延迟大量升高,链接池用光等
• 大key,大概率是热点
各个分片的实际Key个数,
100个key 102个key 容量,应该都大差不差, 102个key
Key1 val1 Key200 val200 但因为根据hash301打散 Key500 val500
key2 val2 key201 val201 的这个key是个 bigkey, key501 val501
… … …
严重造成数据倾斜
key100 val100 key302 val302 key602 val602
• 记录属性(类似行存,或者文本)
- [excellent] 用户做pkey,用户的各个属性,做skey和记录(亲情号) à 均匀,无热点
- [good,可能热点 ] 用商品名做pkey,商品各个属性做skey(商品);可以对部分skey做计数(hincrby)
- [good,可能热点 ] 存放一个电视剧的每一集属性(剧情)
- [medium] 同时增删查改大量属性(hmset/hmget/hgetall), 大range扫描(hscan) à 用户获得编码方便的同时,应当接
受可能的 Latency波动
• 记录同类数据
- [good] 用多个小hash,每个存放100个subkey,用于分批推送(push服务)
- [bad] 用一个hash,存放所有的坏人(游戏) à 导致数据倾斜
Key-value Intersection
New <Set3>
Serialize Store Read De-serialize
<Set> à sobj2 <S2, sobj2> S1 à sobj2’ Sobj2’à <Set>
Create
Set1 [0] [1] ..[m]
Intersection X Y Store Z
Set1 Set2 Set3
Create
Set2 [0] [1] ..[n] Size, Pop, Sort, Interleave, Range(x) …
• Set用法举例
- 友情关系(好友)
- 分组机器信息(平台) à 利用了set的排重性
- 计算找到的中间结果用户递归(计算)
• Set的Trick
- 求 交/并/差 需要hashtag支持
- 同样具有God key的问题(如:VIP用户的亲友团)
- 其他优化途径 – 新浪是如何优化微博粉丝的? à Set在存储内优化,连续存储ID降低开销
大量放置同hashtag会导致数据倾斜,
这种“均热效应”是系统无解的
• Hashtag
- 按{}内 内容做shard,而非key本身
- 大量使用hashtag会导致数据倾斜,和均热:每个都热一点,没有特别热,从而达到单节点瓶颈
• 一般性操作
sadd(alice::fans, emily)
sadd(emily::fans, alice)
• 通过记录冗余,把跨shard变为同shard
sadd({alice}::fans, emily)
sadd({emily}::watching, alice)
sadd({emily}::fans, alice)
sadd({alice}::watching, emily)
• 使用方式
- 各种排行榜(common)
- 按时间排序的消息序列(广告),score是unix-timestamp,优先处理最低分(最老的消息)
- 数据分段查询和临时数据(物流),使用ZRANGEBYSCORE来获取某积分段用户数据,如90分以上的
• Trick
- 比较容易生成common的访问结构,导致godkey的生成 à 做scatter-gather-merge比较困难
- 同样适用ZUNIONSTORE和ZINTERSTORE的时候,会有hashtag的问题
• 怎么做大排行榜?
• Redis的必杀场景
- 基于Sorted-Set(hash+skiplist),靠score来索引排序
- O(log(N))增加/更新/获取当前排名;O(log(N)+M)获取周边排名
• 问题:
- 极易形成单点:集群版数据倾斜/主备分离读单调性
- Sorted-Set不携带value,一般会二次查询
- 用户复合查询:score(double类型)精度不够
• 如何拆:
- 不满足交换律,需要大批量merge
- 不精确的排行榜:基于逻辑分拆和估算
- 精确的排行榜:确定分数的范围先
• Redis的好用之处,就是把常用的数据结构,给结构化掉了
• 更贴近存储对象,是典型的非关系模型
• 副作用:不小心就会搞出大key
• 分布式系统的设计基础:分配律
- Hashtag可以指定分配律
- Bigkey天然break掉这个最基本的设定
- Bigkey,hotkey的本质:分配律维度不够
• Pubsub的典型场景
- 悲观锁(通知更新)
- 简单信号(消息传递)
- 不适合:稳定的更新(会丢消息);1对N的消息转发通道(服务
Application Application
瓶颈);模糊通知(算力瓶颈) 1
SET k k ey
ey 1 1 SET
23 1 2 3 k ey 1
• Transaction OK
R
INC key1
R
INC
INCR
k ey 1 OK
- 伪事务,没有回滚条件 124
124 125
- 集群版需要所有key使用hashtag保证 INCR
k ey 1
- Lua中封装了multi-exec,但更耗费CPU(编译,加载) 125
SCRIPT Load
Guarded by TXN
EVALSHA
1. 脚本的compile-load-run-
unload非常耗费CPU
Run With Param 🔥 Return Result
Script + EVALSHA
2. 整个lua相当于把复杂事务推送到
Redis中执行,如果稍有不慎内存 processCommand
会爆,引擎算力耗光后挂住redis 1. 可以先把脚本在redis中预编译和
加载(不会unload和clean),使
3. Lua在执行时会被封装成redis 用EVALSHA执行
unload
transaction执行,因此跨key的
lua不能正确执行 2. 会比纯EVAL省CPU,但是Redis重
启/切换/变配 code cache会失效,
Cleaning 需要reload
3. 仍是缺陷方案。建议使用复杂数据
Redis 结构,或者module来取代lua
• 对于JIT技术在存储引擎中而言,“EVAL is evil”,尽量避免使用lua耗费内存和计算资源(省事不省心)
• 某些SDK(如Redisson)很多高级实现都内置使用lua,开发者可能莫名走入CPU运算风暴中,须谨慎
高计算消耗
** Redis边界 Wildcard
-- 红色区域代表危险 Lua并发
1对N PUBSUB
N>200
全局配置/热点
企业版(Tair)较好
模块结构化操作
复杂Lua事务
点查 通用命令运算
高并发访问
Keys等扫全表
复杂结构小range
集群mget/mset
超大规模连接数 Streaming慢消费
Huge Batch mget/mset
企业版(Tair)较好
大量冷存
企业版(Tair)较好
Bigkey
审计
大Value Bigkey Range
高网络消耗 如hgetall,smembers 高存储消耗
** 原理解释 2:
• 存储系统的设计和服务的边界
- NoSQL的边界:一致性,事务性
- 高资源消耗是所有系统的边界
• 大系统的设计本质是设计横向扩容(scale io/out)能力
- 业务系统无状态化;避免单点;系统的“锚点”要深,要保护好
- 要考虑存储系统的分配律:如在Redis/Tair中,避免设计出大key,和高资源耗费方式
- 特大型系统在资源使用的特点 **
- 增强调度式资源管理
- fallback访问共享资源的能力(包括存储,缓存,数据库);举例
• 一定会出问题(sooner or later)
- 客户数据量上涨后必然引发的慢查 修改为hash结构:
• 变全表扫描为点查/部分range
- 出现后无能为力 • 虽然hash结构中field太多也会慢,但
比keys性能提升一个到两个数量级
product_1
- 可以在控制台通过危险命令禁用 name : iphone
price : 2999
- 优化
product_23::name product_23::name
product_7788::desc product_7788::desc
product_32123::price product_32123::price
iamotherkey::11 iamotherkey::11
random::name random::name
redis::is::not::ordered name
price
hello::slowlog
redis::is::not::ordered
product_11::whatever
hello::slowlog
…
KEYS命令的模糊匹配: …
product_11::whatever
…
• Redis的存储key是无序的,必然全表扫描 product_1::price
…
…
• Key数目一多必然卡住
…
• hgetall,smembers,lrange,zrange,exhgetall
- 直接与数据结构的subkey(field)多少相关,O(n),携带value爆网卡
- 使用scan来替代
• bitop,bitset
- 设置过远的bit会直接导致OOM
• flushall,flushdb
- 数据丢失
• 配置中和ziplist相关的参数
- 会把部分结构存储成压缩的ziplist结构,开销变大: 删索引,部分查询变O(n),匹配变O(m*n)
- 尽量使用默认参数
• Redis使用方式繁多(Tair更多),合理设计数据结构极大提升性能降低成本
• 避免设计出bigkey (建议不要超过3000),已经避免了90%的Redis/Tair问题
• 尽量为每个缓存数据的key设置合理的TTL
• 理解P99 latency(RT)和偶发性(现代数据的熵的来源);避免tight-retry(建议不低于150ms)
• 最有效降低Redis/Tair的成本方式是:合理使用
• 设计考虑运维窗口,尽量接受主动运维
使用模式 Jedis JedisPool JedisCluster RedisClient RedisClusterClient Single Mode Cluster Mode
Binlog Write
Replication
Ins@Region1
op(1)
Master 1 Slave 1
Binlog发送:
binlog(op(1))
Binlog
1. 引擎生成Binlog发向远端
op(2)
App@Region1 Master 2 Slave 2 2. Merge & Batch write
binlog(op(2)) 3. Exactly once/回环检测
Binlog
op(3)
Master 3 Slave 3
binlog(op(3))
Binlog Replicator
Region1 和Region2是双活环境: /DTS
Replicator
1. 每实例内都有可写master /DTS Ins@Region2
2. 可以支持异构同步(如Region1有
Slave 1 Master 1
3master,Region2有2master,因为各 op(x)
单元服务能力不同) binlog(op(x))
Binlog
App@Region2
op(y)
Slave 2 Master 2
binlog(op(y)) Binlog
多活系统的两个绕不开的问题:
数据回环,Exactly Once
导航时地理位置信息推送:
1. DNS漂移是一个边界效应,通常大概
影响边界上5%-7%的用户
2. 在导航中跨越边界时,会大量出现
交叉访问不同数据区的场景;业务
逻辑复杂,可靠性低,用户体验差
高德交通三地六向同步(Tair only):
1. Redis-enterprise跨域多活提供百万OPS每秒
的数据同步
2. 交通在三地都可高速写入/访问;极高的性能
优势提供流畅的用户体验
redis数据同步 3. 用户可以灵活的在SDK层控制读写,比例等
用户访问
• 登陆态
- 统一登录(SSO)
- 就近高性能访问
- 极大简化业务架构流程
ß 全球分布式session
** Tair全球多活:高SLA保障
Zone A Zone B
Tair T1 Binlog
Tair
T2 T3
Replicator
• 适合写入量不大,就近读取型业务
• 适合1地向N(N>=4)的同步,因为拉到的binlog可被目的端同时消费
• 不适合写入量(包括突发写入)大的业务;binlog易堆积,源端压力大影响log拉取效率,从而影响整个链路
• 适合缓存更新(阿里内部使用经验)
• 任意时间点的数据恢复
00:00:00 set key1 25 00:00:00 set key1 25
00:00:01 zadd k2 1 25 00:00:01 zadd k2 1 25
… …
23:58:05 set key1 val 23:58:05 set key1 val
… …
23:59:59 zadd k2 1 25 23:59:59 zadd k2 1 25
- Backup/Restore的终极形态 Tuesday:
00:00:00 incr key1 1
Tuesday:
00:00:00 incr key1 1
00:00:01 sadd k am 00:00:01 sadd k am
History
- 支持按秒级的数据恢复(可支持到按条) …
23:58:05 lpush l1 et
…
Dataset
…
23:58:05 lpush l1 et
…
23:59:59 zadd k2 23 77 23:59:59 zadd k2 23 77
- 防止删库跑路场景 Wednesday:
00:00:00 set k9 99
Wednesday:
00:00:00 set k9 99
00:00:01 incr k9 1 00:00:01 incr k9 1
• 场景
14:04:55 incr key1 14:04:55 incr key1
14:04:56 FLUSHALL
…
23:59:59 rpop l1
Friday:
- 高级数据安全 00:00:00 del l1
Current
Dataset
00:00:01 zadd k2 7 25
…
Clone实例:
23:58:05 decr key1 1
- 游戏回档 …
23:59:59 del key1
•
•
创建新的实例,将数据恢复至新实例
切换实例的VIP,可以回滚
- 版本降级
热点
- 来源于阿里双11抢购第一秒洪峰的核心技术 离线分析
- 毫秒级发现/打散热点 离线
记录
反馈 /分
析
- HKAR可以抗500-800w的单数据热点(读)
实时感知 阿里云Redis
• 应用场景 热点在线
实时感知
社区版
- 企业级应用的突发热度安全气囊 阿里云Redis
企业版(Tair)
散列
- 大规模突发热点:抢购,热播,突发事件等
- 全局配置 热点散列
- 支持自定义热点(预打散) 2021-07 coming soon
• 电商冷热部署
- 常态:温存(持久内存/容量存储型)
- 更好的成本 Zone: A Zone: B
Master Master
- 更高的数据可靠性
- 大促态:热(增强性能)
- 更强的性能 Sender
Task:1
- 突发热点和抢购
Replica Replica
• 双向复制
Sender
- 企业级双向复制协议支持 Task:2
- 大促前后购买和归还
- 异构容灾
• 来源于为阿里广泛服务的新数据结构
- CAS/CAD:对原有string的增强
- TairString:支持并发的String类型(携带version)
- TairHash:支持在key-field-value中field携带超时的hash结构
- TairDoc:对标reJSON并完全兼容。同时支持JSON Patch和JSON Pointer,提供YAML和XML的转换
- TairBloom:对标RedisBloom并完全兼容
- TairGIS:提供点,线,面的2D位置关系(相交,包含)等查找
- TairTs:对时间序列(TimeSeries)进行存储,构建秒级监控系统
- TairCpc:流失去重计算:安全,防刷/作弊,黄牛等
• 已经在企业版(Tair)上线,并在共享二进制中支持
- https://help.aliyun.com/document_detail/145832.html
• 分布式锁实现的问题
设置
SET resource_1 random_value NX EX 5
删除
CAD resource_1 my_random_value
续约
• 续约(使用CAS) CAS resource_1 my_random_value my_random_value EX 10
• https://help.aliyun.com/document_detail/146758.html
• 携带version的string
- 保证并发更新的原子性
- 通过version来实现更新,乐观锁
- 不能与原来redis sting混用
while(true){
• 更多的语义 {value, version} = exGet(key);
value2 = update(...); /* set new value */
ret = exSet(key, value2, version);
- exINCR/exDECR:抢购 if(ret == OK)
- exCAS:减少网络交互 break; /* success updated */
else if (ret.contanis(“version is stale”))
• https://help.aliyun.com/document_detail/147094.html continue; /* retry */
}
2. Exhash中每个设备(skey),登陆的
- 针对每台设备控制重登陆时间 session时间都是30天,每台设备超时
后会自动失效
- 管理用户设备,针对不同VIP设置 exhset user_1001 iphone <session_ip>
EX 2592000(30 days)
Tai
App
3. 当用户的新设备登陆时,提醒用户已
经到最大值,充值vip或者踢掉在线设
备
用户登陆:
exhlen user_1001
1. 由于媒体设备的增多,一个账号要管理多 user_1001 (65/90 days)
exhgetall user_1001
exhdel user_1001 ipad
台设备的登陆
iphone <session_ip> (21/30days) 4. 用户中心中,对当前登陆设备进行管
2. 主账号,各设备有不同的登录态周期 理
pc <session_pc> (29/30 days)
exgetall user_1001
3. 用户要能够管理自己的设备,和登陆态 ipad <session_pad> (1/30 days)
4. VIP可以允许更多的设备登陆(售卖)
简单而高效!
product::name::iphonex
product::name::iphonex::left
product::name::iphonex::color::gold
product::name::iphonex::color::gold::left
使用exhmsetwithopt就可以同时事务性设置两个skey
exHash接口: 原理就是single-command的atomic性
product::name::iphonex
::left
::color::gold
::color::gold::left
使用 同shard单条query在单线程保证简单原子性
• 完全兼容Redis reJSON模块
用户注册
NodeJS
- 业务可以无缝迁移
- 提供超高速JSON及文档类应用
- 配置中心/前端展示 JSON.SET person .name 'bar'
• 能力增强 修改姓名
NodeJS
- 提供更灵活的前端特性
JSON.GET支持JSON到YAML,XML格式
• 完全兼容Redisbloom模块
• 极小的空间来做存在性判断
• 拥有比RedisBloom更高的精度
① 设备ID是否存在?
bf.exist
②如果返回不存在则走
新设备登陆,更新bloom
设备请求(带设备ID) bf.add
App
②返回没有 ②如果返回存在,
则爬取 因为False Positive
① URL是否爬过? ③DB确认旧设备
bf.exist 特性去DB查询是否真实 可大幅为DB降压
App ③ 添加爬取过URL
bf.add/madd
DB
爬虫系统 大规模新旧设备登录鉴别
一、容量规划 三、推荐去重
1. 将用户按照 userID % SIZE (SIZE为bloom个数) 划分 1. 当需要给用户userID做推荐时,随机挑选部分文章
避免多个Bloom带来源数据开销 2. BF.MEXISTS bloom_i userID:article_1 userID:article_2 …
2. Key使用userID:articleID做划分 return 1 1 1 0 1 1 0 …
二、访问时构建Bloom 四、定期轮转Bloom
1. 当userID访问了articleID时: 1. 为了防止Bloom单个容量过大,且业务逻辑可能只限定
i = userID % SIZE 不重复推荐最近6个月的文章。因此需要按照MySQL中最近
BF.ADD bloom_i userID:articleID 6个月的访问记录来重新生成Bloom
2. INSERT db userID articleID(插入数据库,eg:MySQL)
• 典型的判断“点”和“面”的关系
- 儿童安全:孩子是否在区域内
- 飞行安全:无人机是否在禁飞区内
- 共享单车:是否在归还区域
• 场景:更新频率快,查询量大
- 儿童每次位置都是变化的(x,y),不容易cache
- 频繁的区域更新等,写入压力大
- 替代PostGIS+Cache场景,几十到数百倍性能提升
GIS.ADD user1 primaryschool 'POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))’
GIS.ADD user1 home 'POLYGON ((80 90, 80 80, 90 80, 90 90))’
GIS.INTERSECTS user1 'POINT (30 11)' --> primaryschool
• 2020双11店铺服务
- 商家服务范围(多个polygon)
- 消费者(一个点)
- 关系判断:确定消费者是否在商家
的服务范围中
• 场景
- 更新频率快,查询量大
- 良好的横向扩容能力
TairTs:秒级监控+热点消息缓存
• “尺有所短,寸有所长”
- 专门为秒级监控设计的模块
- 大规模系统的秒级监控与快速问题定位
- 阿里集团ARMS秒级监控支持,双十一大促秒级监控系统
- Grafana等开源可视化监控的集成
• 存储最近指定时间范围的数据,支持系统容
灾或热点访问
- 钉钉会议缓存最近数小时数据,防止数据丢失
- 自动驾驶实验室缓存汽车行驶过程中的监控数据,并提供
高并发访问
• Data Sketches
- CPC(Compressed Probability Counting) sketch用于构建安全风控系统
- 实时风控:防黄牛,anti-robot等
- 用于直接替代flink+Redis或者分析型数据库
- 流式接口: 替代大量的风控中的 groupby() Count()
- 资损控制
• Undocumented
- 文档,示例有需要可以开放
- 阿里安全(神盾局)
• VIP(SLB/NGLB)
• 客户端 • DB
1. 建链接瓶颈(极少)
1. 链接池满 1. 容量,CPU,流量(见前文)
2. 流量不均衡(少)
2. RT高(跨地域,gc等) 2. 主机故障,HA速度
3. 流量瓶颈(极少)
3. 建链接慢(K8s DNS等) 3. 慢查询
4. 大查询,发快收慢
Tair/Redis 80%的问题是RT(latency)相关
后端排查:主要是慢查和CPU排查
• 数据源
- 支持已有备份集
- 支持自动新建备份集
• 支持版本
- 社区版(2.8~6.0)
- 企业版(Tair)
• 支持架构
- 标准版
- 读写分离版
- 集群版
• 离线分析热key
- 方法1:缓存分析也可以分析出相对较热的key
- 方法2:最佳实践,imonitor命令 + redis-faina 分析出热点Key
- 使用须知:仅支持集群架构实例,需自行部署运行;步骤参见下图黑
屏化部分
- 支持cpu、内存、连接使用率、慢SQL维度的健康巡检,生成健康报告,一键查看实例健康状态
• "i"/"r"系列的命令:透过proxy,直接到后端节点
- imonitor/iinfo: 通过index发向db
- https://help.aliyun.com/document_detail/145969.html
• 开启loghub查阅访问日志
- 写审计:不建议常开
- Proxy的慢日志,热日志,建联日志
• Proxy的debug(不建议常态开启)
- 可统计每client的ops
- 输入特殊命令,审计一段时间内来源IP
- 输入特殊key,审计一段时间的来源IP
• DB节点看到的slowlog,IP是Proxy的
- Tair版本会透传映射,社区版本无此能力
• RT的排查是链路的排查
- Top down:先查下应用测多少受影响,看是否是一台,一个pod,或者全部
- Bottom up:优先查阅Tair/Redis和数据库的慢查,告警等
• 优先避免流量型不可控场景
- 每一层都有分流/限流/降级/切换策略
- 流量控制越发生在底层,业务越不可控
• IAAS/PAAS层排查比例升高显著
• Test Coverage
- 可以摸清底层依赖的能力:摸高和长跑测试
- 压测场景覆盖度很大概率决定上线的问题多少
• 为什么要读写分离
INCR version
INCR version
Proxy
- 不好拆的大key GET version ①
GET version ②
- 跨slot的lua GET version ③
• Tair/Redis读写分离的问题 Master
② ① ③
- Lua很难读写分离(除非只读lua用账号硬拆) SET version 1
INCR version
- 不能水平扩展 INCR version
INCR version
- 写瓶颈:混合类命令
• 大量的优化: RO_0 RO_1 RO_2
• Big-key free
- 随时扩缩容
Redis社区版 Redis社区版
- 集群整体latency平整 Tair 主备
集群 读写分离
- 使用hashtag业务更可控 写(key均匀情况) K*分片数 K K*3
• Pros
SDK SDK
- 客户可以方便的使用跨slot命令:
Native Cluster Proxy-bridged
- 阿里云的proxy几乎兼容所有的命令 Access Access
- mget/mset/rename/keys/sinterstore
…
- 用户短链接场景,被隔离在proxy外
VIP VIP VIP VIP
- Proxy具有引擎的聚合能力,提升db性能
• Cons Proxy
Proxy Proxy
- 做为一般性网元,进出延时映射成架构成本(0.2~0.3 ms)
- 网元越多,受整体宕机率影响越大
- Proxy和DB有一个重传,客户必然抖动
- 吞吐容易爆/内存容易堆 …
db_0 db_1 db_n
… db • readonly_lua_route_ronode_
db_master db_ro1 db_ro2 enable,开启该配置会判断
db_0 db_1 db_n
lua脚本中是否包含写操作,
对于只读lua请求也会按读写
主从版本到集群版本无缝迁移 聚合SDK连接,提升集群吞吐 提供读写分离 分离策略路由
sub-ins sub-ins
App
Relay App
Proxy
sub-ins sub-ins
sub-ins sub-ins
App App
sub-ins sub-ins
• Redis Proxy能力升级(TBD)
Redis Memcache ProtoBuf TairSQL
- Proxy变为gateway,提供更强的兼容力和可扩展
- 兼容memcache
Redis-Mesh
- 云服务对PB/SQL接入需要
- Couchbase/Aerospike KV系列命令兼容 Redis-Mesh Redis-Mesh
- 底层可使用企业版的双擎
• 双擎切换
- 来源于阿里内部的常态化部署
- 常态:持久化存储,更好的可靠性和成本
- 大促态:内存,更好的性能和服务能力 持久化/混合存储 性能增强版
Tair Tair
②
④
DTS
① DB DB
③
顺序一致性
1. 由于脏cache的情况,在远程同步过程中,只能有底层数据源同步,满足 -> 1 近端数据源更新 -> 2 近端cache更新 -> 3 数据源同步至远端 -> 4
更新远端cache
2. 如果cache同步,底层数据源没有同步过去,那么远端数据库会出现大量脏写,导致逻辑错误。且无法消解
3. 使用DTS来watch binlog,更新cache(配一下即可)
- 依靠逻辑时钟+规则
T0: mylist: { A, B, C } T0: mylist: { A, B, C }
- 性能严重退化 T2: mylist: { A, B, C,D } T2: mylist: { A, B, C,E }
- 用户规则学习成本高 T3: mylist: { A, B, C,D, E } T3: mylist: { A, B, C,E, D }
• 学术意义大于工程意义
腾峰(李竟成),阿里云数据库内核工程师,swapdb前作者
”swapdb同样设计了keys的冷热换入换出,amber是更商业化的版本。但实际使用中
最大的问题还是业务要求较低的RT,还是要使用大内存来扛,并不能特别节省内存。
所以最后阿里云还是使用全冷加缓存的方式。”
暴跳(陈宗志),阿里云数据库内核工程师,Pika前作者
”Pika的设计主要围绕成本,在兼容性上做了一些取舍,比较适合特定公司的特定场景。
Pika后续有很多计划,通过优化编码和查询缓存可以获得很好的综合性能,这也是
阿里云新一代混合存储系列主打的方向”
征衡(王正恒),阿里云数据库内核工程师,阿里PDB/PENA作者
”阿里集团在电商上有非常好的冷热分层场景,在冷热置换上也尝试过交换和热缓存
两种方式,随着应用场景成熟我们越来越清晰的理解到通用冷存的重要性。通过
新硬件的引入和设施云化,给用户更多更好的选择,在性能和TCO上做平衡。”
** Fire-And-Forget:播放记录
推送系统
server
Fire-And-Forget:
-c
show
IST user-y
HE X
1. 优酷全站用户在使用中,
需要实时记录播放记录和
点位,并在多设备中漫游
HGE
TALL
2. 当用户登陆,搜索,个人 user
-x
中心要实时被展示;接受
push链路的条件查询,精
准实时推送
全异步redis(Tair only) 用户中心
3. 传统的“问-答”模式,并 HSET user-x show-a pos-1 1. 使用redis全异步协议栈,全
不能发挥playlog的极限性 pipeline发送,忽略返回 server
HSET user-y show-a pos-3
能(需要等到答案再发下
一个);在查询-推荐,和 HSET user-z show-b pos-5
2. 实现数千万每秒的播放记录保存
推送系统,需要精准定位, …
提高用户粘度 能力,并在1ms内查询出最新结
HSET user-p show-c pos-7
果,提供给用户中心使用,或推
送系统等进行实时决策
playlog 3. 无需引入庞大的大数据计算系统,
架构更简单,系统更高效
Tai Tai Canonical Async
server server
Ask-and-Answer