利用Redis实现SQL伸缩的方法
本篇文章向大家介绍《利用Redis实现SQL伸缩的方法》,主要包括Redissql伸缩,具有一定的参考价值,需要的朋友可以参考一下。
这篇文章主要介绍了利用Redis实现SQL伸缩的方法,包括讲到了锁和时间序列等方面来提升传统数据库的性能,需要的朋友可以参考下。
缓解行竞争
我们在Sentry开发的早起采用的是sentry.buffers。 这是一个简单的系统,它允许我们以简单的Last Write Wins策略来实现非常有效的缓冲计数器。 重要的是,我们借助它完全消除了任何形式的耐久性 (这是Sentry工作的一个非常可接受的方式)。
操作非常简单,每当一个更新进来我们就做如下几步:
- 创建一个绑定到传入实体的哈希键(hash key)
- 使用HINCRBY使计数器值增加
- HSET所有的LWW数据(比如 "最后一次见到的")
- 用当前时间戳ZADD哈希键(hash key)到一个"挂起" set
现在每一个时间刻度 (在Sentry中为10秒钟) 我们要转储(dump)这些缓冲区并且扇出写道(fanout the writes)。 看起来像下面这样:
- 使用ZRANGE获取所有的key
- 为每一个挂起的key发起一个作业到RabbitMQ
现在RabbitMQ作业将能够读取和清除哈希表,和“悬而未决”更新已经弹出了一套。有几件事情需要注意:
- 在下面我们想要只弹出一个设置的数量的例子中我们将使用一组排序(举例来说我们需要那100个旧集合)。
- 假使我们为了处理一个键值来结束多道排序的作业,这个人会得到no-oped由于另一个已经存在的处理和清空哈希的过程。
- 该系统能够在许多Redis节点上不断扩展下去仅仅是通过在每个节点上安置把一个'悬置'主键来实现。
我们有了这个处理问题的模型之后,能够确保“大部分情况下”每次在SQL中只有一行能够被马上更新,而这样的处理方式减轻了我们能够预见到的锁问题。考虑到将会处理一个突然产生且所有最终组合在一起进入同一个计数器的数据的场景,这种策略对Sentry用处很多。
速度限制
出于哨兵的局限性,我们必须终结持续的拒绝服务攻击。我们通过限制连接速度来应对这种问题,其中一项是通过Redis支持的。这无疑是在sentry.quotas范围内更直接的实现。
它的逻辑相当直接,如同下面展示的那般:
def incr_and_check_limit(user_id, limit):
key = '{user_id}:{epoch}'.format(user_id, int(time() / 60))
pipe = redis.pipeline()
pipe.incr(key)
pipe.expire(key, 60)
current_rate, _ = pipe.execute()
return int(current_rate) > limit
我们所阐明的限制速率的方法是 Redis在高速缓存服务上最基本的功能之一:增加空的键字。在高速缓存服务中实现同样的行为可能最终使用这种方法:
def incr_and_check_limit_memcache(user_id, limit):
key = '{user_id}:{epoch}'.format(user_id, int(time() / 60))
if cache.add(key, 0, 60):
return False
current_rate = cache.incr(key)
return current_rate > limit
事实上我们最终采取这种策略可以使哨兵追踪不同事件的短期数据。在这种情况下,我们通常对用户数据进行排序以便可以在最短的时间内找到最活跃用户的数据。
基本锁
虽然Redis的是可用性不高,我们的用例锁,使其成为工作的好工具。我们没有使用这些在哨兵的核心了,但一个示例用例是,我们希望尽量减少并发性和简单无操作的操作,如果事情似乎是已经在运行。这对于可能需要执行每隔一段时间类似cron任务非常有用,但不具备较强的协调。
在Redis的这样使用SETNX操作是相当简单的:
from contextlib import contextmanagerr = Redis()@contextmanagerdef lock(key, nowait=True):
while not r.setnx(key, '1'):
if nowait:
raise Locked('try again soon!')
sleep(0.01)
# limit lock time to 10 seconds
r.expire(key, 10)
# do something crazy
yield
# explicitly unlock
r.delete(key)
而锁()内的哨兵利用的memcached的,但绝对没有理由我们不能在其切换到Redis。
时间序列数据
近来我们创造一个新的机制在Sentry(包含在sentry.tsdb中) 存储时间序列数据。这是受RRD模型启发,特别是Graphite。我们期望一个快速简单的方式存储短期(比如一个月)时间序列数,以便于处理高速写入数据,特别是在极端情况下计算潜在的短期速率。尽管这是第一个模型,我们依旧期望在Redis存储数据,它也是使用计数器的简单范例。
在目前的模型中,我们使用单一的hash map来存储全部时间序列数据。例如,这意味所有数据项在都将同一个哈希键拥有一个数据类型和1秒的生命周期。如下所示:
{
"<type enum>:<epoch>:<shard number>": {
"<id>": <count>
}} </count></id></shard></epoch></type>
因此在这种状况,我们需要追踪事件的数目。事件类型映射到枚举类型"1".该判断的时间是1s,因此我们的处理时间需要以秒计。散列最终看起来是这样的:
{
"1:1399958363:0": {
"1": 53,
"2": 72,
}}
一个可修改模型可能仅使用简单的键并且仅在存储区上增加一些增量寄存器。
"1:1399958363:0:1": 53
我们选择哈希映射模型基于以下两个原因:
我们可以将所有的键设为一次性的(这也可能产生负面影响,但是目前为止是稳定的)
大幅压缩键值,这是相当重要的处理
此外,离散的数字键允许我们在将虚拟的离散键值映射到固定数目的键值上,并在此分配单一存储区(我们可以使用64,映射到32个物理结点上)
现在通过使用 Nydus和它的map()(依赖于一个工作区)(),数据查询已经完成。这次操作的代码是相当健壮的,但幸好它并不庞大。
def get_range(self, model, keys, start, end, rollup=None):
""" To get a range of data for group ID=[1, 2, 3]: Start and end are both inclusive. >>> now = timezone.now() >>> get_keys(tsdb.models.group, [1, 2, 3], >>> start=now - timedelta(days=1), >>> end=now) """
normalize_to_epoch = self.normalize_to_epoch
normalize_to_rollup = self.normalize_to_rollup
make_key = self.make_key
if rollup is None:
rollup = self.get_optimal_rollup(start, end)
results = []
timestamp = end
with self.conn.map() as conn:
while timestamp >= start:
real_epoch = normalize_to_epoch(timestamp, rollup)
norm_epoch = normalize_to_rollup(timestamp, rollup)
for key in keys:
model_key = self.get_model_key(key)
hash_key = make_key(model, norm_epoch, model_key)
results.append((real_epoch, key, conn.hget(hash_key, model_key)))
timestamp = timestamp - timedelta(seconds=rollup)
results_by_key = defaultdict(dict)
for epoch, key, count in results:
results_by_key[key][epoch] = int(count or 0)
for key, points in results_by_key.iteritems():
results_by_key[key] = sorted(points.items())
return dict(results_by_key)
归结如下:
- 生成所必须的键。
- 使用工作区,提取所有连接操作的最小结果集(Nydus负责这些)。
- 给出结果,并且基于指定的时间间隔内和给定的键值将它们映射到当前的存储区内。
今天关于《利用Redis实现SQL伸缩的方法》的内容介绍就到此结束,如果有什么疑问或者建议,可以在golang学习网公众号下多多回复交流;文中若有不正之处,也希望回复留言以告知!
Redis的11种Web应用场景简介
- 上一篇
- Redis的11种Web应用场景简介
- 下一篇
- 从MySQL到Redis的简单数据库迁移方法
-
- 数据库 · Redis | 11小时前 |
- 监控Redis集群健康状态的工具与指标
- 112浏览 收藏
-
- 数据库 · Redis | 1星期前 |
- Redis数据安全防护全攻略
- 252浏览 收藏
-
- 数据库 · Redis | 2星期前 |
- Redis主从复制故障排查与修复技巧
- 302浏览 收藏
-
- 数据库 · Redis | 2星期前 |
- Redis与HBase存储方案详解
- 325浏览 收藏
-
- 数据库 · Redis | 2星期前 |
- Redis数据安全防护全攻略
- 157浏览 收藏
-
- 数据库 · Redis | 2星期前 |
- 高并发Redis优化技巧分享
- 257浏览 收藏
-
- 数据库 · Redis | 2星期前 |
- Redis数据安全防护全攻略
- 398浏览 收藏
-
- 数据库 · Redis | 3星期前 |
- Redis配置加密方法与安全设置
- 232浏览 收藏
-
- 数据库 · Redis | 3星期前 |
- RedisHyperLogLog高效统计技巧
- 283浏览 收藏
-
- 数据库 · Redis | 3星期前 |
- Redis与MySQL缓存同步方法详解
- 141浏览 收藏
-
- 数据库 · Redis | 3星期前 |
- Redis布隆过滤器防穿透原理解析
- 312浏览 收藏
-
- 数据库 · Redis | 1个月前 |
- Redis容器化部署实战技巧分享
- 195浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- ChatExcel酷表
- ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
- 3164次使用
-
- Any绘本
- 探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
- 3376次使用
-
- 可赞AI
- 可赞AI,AI驱动的办公可视化智能工具,助您轻松实现文本与可视化元素高效转化。无论是智能文档生成、多格式文本解析,还是一键生成专业图表、脑图、知识卡片,可赞AI都能让信息处理更清晰高效。覆盖数据汇报、会议纪要、内容营销等全场景,大幅提升办公效率,降低专业门槛,是您提升工作效率的得力助手。
- 3405次使用
-
- 星月写作
- 星月写作是国内首款聚焦中文网络小说创作的AI辅助工具,解决网文作者从构思到变现的全流程痛点。AI扫榜、专属模板、全链路适配,助力新人快速上手,资深作者效率倍增。
- 4509次使用
-
- MagicLight
- MagicLight.ai是全球首款叙事驱动型AI动画视频创作平台,专注于解决从故事想法到完整动画的全流程痛点。它通过自研AI模型,保障角色、风格、场景高度一致性,让零动画经验者也能高效产出专业级叙事内容。广泛适用于独立创作者、动画工作室、教育机构及企业营销,助您轻松实现创意落地与商业化。
- 3785次使用
-
- redis复制有可能碰到的问题汇总
- 2023-01-01 501浏览
-
- 使用lua+redis解决发多张券的并发问题
- 2023-01-27 501浏览
-
- Redis应用实例分享:社交媒体平台设计
- 2023-06-21 501浏览
-
- 使用Python和Redis构建日志分析系统:如何实时监控系统运行状况
- 2023-08-08 501浏览
-
- 如何利用Redis和Python实现消息队列功能
- 2023-08-16 501浏览

