redis的双重hash作用

Redis 的双重哈希(Double Hashing)通常是指在 Redis 集群中使用的一种数据分片和节点定位机制。这种机制主要包含两个哈希步骤:

  1. 第一层哈希:使用 CRC16 算法对键(key)进行哈希,然后对 Redis 集群的哈希槽(hash slots)数量进行取模,从而将键映射到一个特定的哈希槽。
  2. 第二层哈希:当需要重新分片或者节点增加/减少时,为了保证数据迁移的最小化,Redis 集群使用虚拟节点(virtual nodes)的概念。每个物理节点可以有多个虚拟节点,每个虚拟节点也是一个哈希槽。这样,键通过第一层哈希确定的哈希槽可能会映射到不同的虚拟节点上,而这些虚拟节点再映射到实际的物理节点上。

双重哈希的优势包括:

  • 均匀分布:通过双重哈希,可以更均匀地将数据分布到各个节点,减少某些节点过载而其他节点空闲的情况。
  • 容错性:当某个节点失败时,只有映射到该节点的哈希槽需要重新分配,而不是整个键空间,这样可以减少数据迁移的开销。
  • 灵活性:在增加或减少节点时,只需要重新分配部分哈希槽,而不是全部,这样可以减少数据迁移的开销,提高系统的灵活性。

此外,Redis 集群使用这种机制可以实现数据的高可用性和可扩展性,同时保持较低的数据迁移成本和较高的数据访问效率。

原子性

Lua 本身并没有提供对于原子性的直接支持,它只是一种脚本语言,通常是嵌入到其他宿主程序中运行,比如 Redis。在 Redis 中执行 Lua 脚本的原子性是指:整个 Lua 脚本在执行期间,不会被其他客户端的命令打断。

这意味着,当 Redis 执行 Lua 脚本时,Redis 会把 Lua 脚本作为一个整体并把它当作一个任务加入到一个队列中,然后单线程按照队列的顺序依次执行这些任务,在执行过程中 Lua 脚本是不会被其他命令或请求打断,因此可以保证每个任务的执行都是原子性的。

例如,假设我们要将某个值加上1,并且只有在这个值小于10的情况下才能执行加1操作,那么可以使用一下 Lua 脚本来实现:

lua 复制代码
if redis.call('GET', 'value') < 10 then
    redis.call('INCR', 'value')
return 1
else
return 0
end

在redis中整个 Lua 脚本作为一个整体被执行且不被其他事务打断,这就是一个原子性的操作。

此外,Redis 通过 eval、evalsha 等命令来执行 Lua 脚本。但是,Lua 脚本如何保证原子性呢?在 Redis 中,Lua 脚本能够保证原子性的主要原因还是 Redis 采用了单线程执行模型。也就是说,当 Redis 执行 Lua 脚本时,Redis 会把 Lua 脚本作为一个整体并把它当作一个任务加入到一个队列中,然后单线程按照队列的顺序依次执行这些任务,在执行过程中 Lua 脚本是不会被其他命令或请求打断,因此可以保证每个任务的执行都是原子性的。

总结来说,在 Redis 中,Lua 脚本的原子性是由 Redis 的单线程执行模型保证的,这使得 Lua 脚本在执行期间不会被其他客户端的命令打断,从而确保了操作的原子性。

redis管道:就是相当于队列,开启一个管道传入多条redis命令可以实现串行化执行。

redis的事务是弱事务,可以通过使用lua增强事务

虚拟节点机制通过引入额外的虚拟节点来提高数据分布的均匀性。在一致性哈希算法中,每个节点(或服务器)和每个键(或数据)都被映射到一个哈希环上。数据通常被存储在环上顺时针方向遇到的第一个节点上。如果没有虚拟节点,当节点数量较少时,数据可能会非常不均匀地分布在节点上,导致某些节点过载而其他节点空闲。

通过引入虚拟节点,可以使得数据在节点间分布得更加均匀。每个物理节点可以有多个虚拟节点,这些虚拟节点在哈希环上均匀分布。当定位数据时,首先根据键的哈希值找到对应的虚拟节点,然后根据虚拟节点映射到实际的物理节点上。

这样做的好处包括:

  1. 提高系统的稳定性:即使在节点增减的情况下,也可以保证数据分布的相对稳定。
  2. 减少对系统的冲击:在节点变化时,只有部分数据需要迁移,从而减少了对系统的冲击。
  3. 数据均匀分布:通过虚拟节点,可以使得数据在节点间分布得更加均匀。

实际作用:如果一个物理节点对应多个虚拟节点,那么这些虚拟节点均匀分布在哈希环上,当增加或减少节点时,只有与这些虚拟节点相关联的数据需要重新分配,而不是整个键空间。这样可以减少数据迁移的开销,提高系统的灵活性。 总结来说,虚拟节点通过在哈希环上创建更多的节点位置,使得数据可以更加均匀地分布在各个物理节点上,从而提高了数据分布的均匀性,并且在节点增减时减少了数据迁移的开销。

相关推荐
不爱学习的YY酱28 分钟前
【Linux】<共享内存应用>——模拟实现不同进程把hello字符对<共享内存文件对象>的放入和取出操作
linux·数据库·nosql
网络安全指导员43 分钟前
SQL注入的那些面试题总结
数据库·sql·安全·web安全·系统安全
奈斯ing1 小时前
【Oracle篇】SQL性能优化实战案例(从15秒优化到0.08秒)(第七篇,总共七篇)
运维·数据库·sql·oracle·性能优化
Karoku0661 小时前
【企业级分布式系统】ELK-企业级日志分析系统
运维·数据库·redis·mysql·elk·缓存
小小宇宙中微子1 小时前
mysql 命名约束
数据库·sql·oracle
是店小二呀1 小时前
【C++】右值引用与移动语义详解:如何利用万能引用实现完美转发
c++·redis
linweidong2 小时前
MariaDB面试题及参考答案
linux·运维·数据库·负载均衡·dba·mariadb·后端面试
PGCCC4 小时前
【PGCCC】Postgresql 缓存替换算法
数据库·缓存·postgresql
盖盖衍上4 小时前
4. SQL视图
数据库·sql