HandlerSocket 事务

发布于 2025-01-04 07:22:55 字数 254 浏览 2 评论 0原文

在Redis中可以通过这种方式完成事务:

redis.watch('powerlevel')
current = redis.get('powerlevel')
redis.multi()
redis.set('powerlevel', current + 1)
redis.exec()
  1. 是否可以使用HandlerSocket来执行此操作?
  2. 使用交易提供的处理程序有哪些一般功能?

In Redis can complete the transaction in this way:

redis.watch('powerlevel')
current = redis.get('powerlevel')
redis.multi()
redis.set('powerlevel', current + 1)
redis.exec()
  1. Is it possible to perform this operation using the HandlerSocket?
  2. What are the general features for working with transaction provides handlersotsket?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

小鸟爱天空丶 2025-01-11 07:22:55

将 Redis“事务”与通用事务引擎进行比较总是有点误导。 Redis WATCH/MULTI/EXEC 块是:

  • 非原子性(出现错误时不会回滚)
  • 一致性(Redis 没有太多一致性规则)
  • 完全隔离(一切都是序列化的)
  • 如果选择 AOF+fsync 策略,则可能是持久的

因此Redis 并未完全提供通常用于定义事务的完整 ACID 属性。与大多数事务引擎相反,Redis 提供非常强的隔离性,并且不尝试提供任何回滚功能。

问题中提供的示例并不是真正具有代表性的 IMO,因为只需使用以下方法即可以更简单的方式实现相同的行为:

redis.incr( "powerlevel" )

因为 Redis single 操作始终是原子的,并且孤立。

当必须强制各个键之间的一致性或实现乐观锁定模式时,通常使用 WATCH/MULTI/EXEC 块。换句话说,如果您的目的只是增加隔离计数器,则无需使用 WATCH/MULTI/EXEC 块。

HandlerSocket 是一个完全不同的野兽。它构建在 MySQL 的通用处理程序之上,根据底层存储引擎的不同,事务行为会有所不同。例如,当它与MyISAM一起使用时,它将不使用ACID事务,但将通过表级别的R/W锁来确保一致性。对于 InnoDB,ACID 事务将与默认隔离级别一起使用(可以在 InnoDB 配置中设置 AFAIK)。 InnoDB实现MVCC(多版本并发控制),因此锁定比MyISAM复杂得多。

HandlerSocket 使用两个工作线程池(一个用于只读连接,一个用于面向写入的连接)。人们应该使用多个读取工作线程,但只使用一个写入线程(可能是为了减少锁定争用)。因此,在基本配置中,写入操作是序列化的,但读取操作不是序列化的。 AFAIK,与 Redis 具有相同隔离语义的唯一可能是仅使用面向写的套接字来执行读和写操作,并仅保留一个写线程(所有操作的完全序列化)。但这会影响可扩展性。

从HandlerSocket协议来看,无法访问事务功能。在每次事件循环迭代中,它都会收集所有操作(来自所有套接字),并为所有这些操作执行唯一的事务(仅与 InnoDB 相关)。 AFAIK,用户无法更改此交易的范围。

结论是,通常不可能使用 HandlerSocket 模拟 Redis WATCH/MULTI/EXEC 块的行为。

现在,回到示例,如果目的只是以一致的方式递增计数器,则 HandlerSocket 协议。例如,可以使用+/-(递增/递减)操作,也可以使用U?操作(类似于 Redis GETSET 命令),或 +?/-? (递增/递减,返回之前的值)。

Comparing Redis "transactions" to a general purpose transactional engine is always a bit misleading. A Redis WATCH/MULTI/EXEC block is:

  • Not atomic (no rollback in case of error)
  • Consistent (there are not many consistency rules anyway with Redis)
  • Fully isolated (everything is serialized)
  • Possibly durable if AOF+fsync strategy is selected

So the full ACID properties which are commonly used to define a transaction are not completely provided by Redis. Contrary to most transactional engines, Redis provides very strong isolation, and does not attempt to provide any rollback capabilities.

The example provided in the question is not really representative IMO, since the same behavior can be achieved in a simpler way by just using:

redis.incr( "powerlevel" )

because Redis single operations are always atomic and isolated.

WATCH/MULTI/EXEC blocks are typically used when consistency between various keys must be enforced, or to implement optimistic locking patterns. In other words, if your purpose is just to increment isolated counters, there is no need to use a WATCH/MULTI/EXEC block.

The HandlerSocket is a complete different beast. It is built on top of the generic handler of MySQL, and depending on the underlying storage engine, the transactional behavior will be different. For instance when it is used with MyISAM, it will use no ACID transactions, but consistency will be ensured by a R/W lock at the table level. With InnoDB, ACID transactions will be used with the default isolation level (which can be set in the InnoDB configuration AFAIK). InnoDB implements MVCC (multi-versioning concurrency control), so locking is much more complex than with MyISAM.

The HandlerSocket works with two pools of worker threads (one for read-only connections, one for write oriented connections). People are supposed to use several read worker threads, but only one write thread though (probably to decrease locking contention). So in the base configuration, write operations are serialized, but not read operations. AFAIK, the only possibility to have the same isolation semantic than Redis is to only use the write oriented socket to perform both read and write operations, and keep only one write thread (full serialization of all operations). It will impact scalability though.

From the HandlerSocket protocol, there is no access to transactional capabilities. At each event loop iteration, it collects all the operations (coming from all the sockets), and perform a unique transaction (only relevant with InnoDB) for all these operations. AFAIK, the user has no way to alter the scope of this transaction.

The conclusion is it is not generally possible to emulate the behavior of a Redis WATCH/MULTI/EXEC block with HandlerSocket.

Now, back to the example, if the purpose is just to increment counters in a consistent way, this is fully supported by the HandlerSocket protocol. For instance, the +/- (increment/decrement) operations are available, and also the U? operation (similar to Redis GETSET command), or +?/-? (increment/decrement, returning the previous value).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文