HandlerSocket 事务
在Redis中可以通过这种方式完成事务:
redis.watch('powerlevel')
current = redis.get('powerlevel')
redis.multi()
redis.set('powerlevel', current + 1)
redis.exec()
- 是否可以使用HandlerSocket来执行此操作?
- 使用交易提供的处理程序有哪些一般功能?
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()
- Is it possible to perform this operation using the HandlerSocket?
- What are the general features for working with transaction provides handlersotsket?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
将 Redis“事务”与通用事务引擎进行比较总是有点误导。 Redis WATCH/MULTI/EXEC 块是:
因此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:
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).