iis服务器助手广告
返回顶部
首页 > 资讯 > 数据库 >利用Redis实现SQL伸缩的方法简介
  • 405
分享到

利用Redis实现SQL伸缩的方法简介

伸缩简介方法 2022-06-04 17:06:23 405人浏览 八月长安
摘要

缓解行竞争 我们在Sentry开发的早起采用的是sentry.buffers。 这是一个简单的系统,它允许我们以简单的Last Write Wins策略来实现非常有效的缓冲计数器。 重要的是,我们借助它完全

缓解行竞争

我们在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>

    }}


因此在这种状况,我们需要追踪事件的数目。事件类型映射到枚举类型"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无疑是很适合的。它的文档是那样让人惊讶,那是因为(阅读)其文档的门槛非常的低。虽然他也有折衷(主要是如果你使用持久化),但是他们工作地很好并且比较直观。

那么Redis为您解决什么问题呢?

您可能感兴趣的文档:

--结束END--

本文标题: 利用Redis实现SQL伸缩的方法简介

本文链接: https://www.lsjlt.com/news/11737.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Redis中的BloomFilter简介及使用方法
    本篇内容主要讲解“Redis中的BloomFilter简介及使用方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Redis中的BloomFilter简介及使用...
    99+
    2024-04-02
  • 怎么在Android中利用ScrollView 实现一个伸缩放大效果
    这篇文章给大家介绍怎么在Android中利用ScrollView 实现一个伸缩放大效果,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。核心的控件就是下面的这段代码:package com.kokjuis.tra...
    99+
    2023-05-31
    android scrollview roi
  • 使用Redis实现秒杀功能的简单方法
    1. 怎样预防数据库超售现象 设置数据库事务的隔离级别为Serializable(不可用) Serializable就是让数据库去串行化的去执行事务,一个事务执行完才能去执行下一个事...
    99+
    2024-04-02
  • 如何使用setimmediate实现可伸缩执行的脚本
    这篇文章主要介绍“如何使用setimmediate实现可伸缩执行的脚本”,在日常操作中,相信很多人在如何使用setimmediate实现可伸缩执行的脚本问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操...
    99+
    2024-04-02
  • 利用Nginx实现URL重定向的简单方法
    目录1. 概述2. 使用 Nginx 实现 URL 的重定向2.1 使用场景2.2 单纯的重定向2.3 依据原 URL 重定向补充:Nginx根据url参数重定向1.判断url路径2...
    99+
    2024-04-02
  • Redis实现延迟队列方法介绍
    延迟队列,顾名思义它是一种带有延迟功能的消息队列。那么,是在什么场景下我才需要这样的队列呢? 1. 背景 我们先看看以下业务场景: 当订单一直处于未支付状态时,如何及时的关闭订单如何定期检查处于退款状态的订单是否已经退款成功在订单长时间没有...
    99+
    2023-09-17
    redis java java-rabbitmq
  • Java压缩文件夹最实用简单的方法
    Java 有一个很好的类库来处理 zip 文件。这些类在 java.util.zip 包中可用。以下 Java 示例程序展示了如何使用 java.util.zip 类创建整个文件夹的...
    99+
    2022-11-13
    Java 压缩文件夹
  • 利用Redis实现访问次数限流的方法详解
    假设我们要做一个业务需求,这个需求就是限制用户的访问频次。比如1分钟内只能访问20次,10分钟内只能访问200次。因为是用户维度的场景,性能肯定是要首先考虑,那么适合这个场景的非Re...
    99+
    2024-04-02
  • 利用Go Plugin实现插件化编程的简单方法
    目录前言1.快速开始2.注意事项总结前言 说到插件这个东西,很多人都不陌生,一般来说,插件化有几个好处,一个是增加程序扩展性,丰富功能。另外,还可以实现热更新,有些大型应用,动辄几个...
    99+
    2024-04-02
  • 基于Redis的分布式锁的简单实现方法
    Redis官方给出两种思路 第一种:SET key value [EX seconds] [PX milliseconds] NX 第二种:SETNX+GETSET 首先,分别看一下这几个命令 SET命令 ...
    99+
    2024-04-02
  • Python3压缩和解压缩的实现方法
    这篇文章主要为大家展示了Python3压缩和解压缩的实现方法,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带大家一起来研究并学习一下“Python3压缩和解压缩的实现方法”这篇文章吧。python可以做什么Python是一种...
    99+
    2023-06-06
  • Redis使用Bitmap的方法实现
    目录1. Bitmap 是什么2. 占用存储空间3. 命令3.1 SETBIT3.2 GETBIT3.3 BITCOUNT3.4 BITOP3.5 BITPOS1. Bitmap 是什么 Bitmap(也称为位数组或者位...
    99+
    2023-01-28
    Redis使用Bitmap
  • css实现页面背景图片的拉伸方法
    本篇内容主要讲解“css实现页面背景图片的拉伸方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“css实现页面背景图片的拉伸方法”吧!代码如下:<span...
    99+
    2024-04-02
  • 如何用 C++ 函数设计和实现可伸缩的并发系统?
    通过遵循原子性、线程安全性、可重用性原则,并利用线程、锁、原子变量等机制,c++++ 提供了创建可扩展并发系统所需的强大特性,例如并行求和等实战案例中所示。 利用 C++ 函数构建可扩...
    99+
    2024-04-27
    c++ 并发系统
  • 利用Redis如何实现令牌桶算法
    小编给大家分享一下利用Redis如何实现令牌桶算法,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!在限流算法中有一种令牌桶算法,该...
    99+
    2024-04-02
  • redis实现扩容的方法
    小编给大家分享一下redis实现扩容的方法,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!扩容:1.集群,使用代理,达到集群的目的...
    99+
    2024-04-02
  • css实现禁止缩放的方法
    这篇文章主要介绍“css实现禁止缩放的方法”,在日常操作中,相信很多人在css实现禁止缩放的方法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”css实现禁止缩放的方法”的疑惑有所帮助!接下来,请跟着小编一起来...
    99+
    2023-06-14
  • css首行缩进的实现方法
    这篇文章主要为大家展示了css首行缩进的实现方法,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带大家一起来研究并学习一下“css首行缩进的实现方法”这篇文章吧。css是什么意思css是一种用来表现HTML或XML等文件样式的...
    99+
    2023-06-06
  • Java Jwt库的简介及使用方法
    这期内容当中小编将会给大家带来有关Java Jwt库的简介及使用方法,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。JWT介绍JWT概念JWT , 全写JSON Web Token, 是开放的行业标准RFC...
    99+
    2023-06-25
  • JavaScript实现图像压缩的方法
    目录一、简单压缩二、使用canvas 将base64 图像压缩到指定文件大小以内1、 方法一2.、方法二三、使用 canvas 和 web workers 来实现图像压缩J...
    99+
    2023-01-11
    js 图像压缩 canvas web workers 图像压缩 js canvas压缩
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作