Nginx一致性哈希模块的Lua实现
Nginx一致性哈希模块的Lua重新实现
技术背景:
最近在工作中使用了nginx+redis 的架构,redis在后台做分布式存储,每个redis都存放不同的数据,这些数据都是某门户网站通过Hadoop分析出来的用户行为日志,key是uid,value是user profile,每小时更新量在500-800万条记录,而这些记录一旦生成,我需要在5分钟左右的时间完成所有导入过程。
首先,我在nginx中使用了第三方模块HttpUpstreamConsistent来做负载均衡策略,针对不同用户(uid)选取不同的backend redis:
upstream somestream {
consistent_hash $arg_uid;
server 10.50.1.3:;
server 10.50.1.4:;
server 10.50.1.5:;
}
现在问题来了,由于Hadoop系统处理日志的速度非常快,如果把每条记录都通过Nginx来写入Redis中,这样的速度是无法接受的,而且会影响Nginx对正常请求的服务能力。所以,需要将这些数据以离线的方式导入redis集群中,这样就要重新实现HttpUpstreamConsistent模块了,才能保证读写的哈希策略一致。
下面的源码演示了如何将HttpUpstreamConsistent模块翻译成Lua的过程,(使用了CRC32作散列,依赖库的路径已列在Reference中)。
#!/usr/bin/lua -- chenqi@2014/04/02
--[Reference]
--https://github.com/yaoweibin/ngx_http_consistent_hash
--https://github.com/davidm/lua-digest-crc32lua local CRC = require('CRC32') local M = {} local CONSISTENT_BUCKETS =
local VIRTUAL_NODE = local HASH_PEERS = {}
local CONTINUUM = {}
local BUCKETS = {} local function hash_fn(key)
return CRC.crc32(key)
end -- in-place quicksort
function quicksort(array,compareFunc)
quick(array,,#array,compareFunc)
end function quick(array,left,right,compareFunc)
if(left < right ) then
local index = partion(array,left,right,compareFunc)
quick(array,left,index-,compareFunc)
quick(array,index+,right,compareFunc)
end
end function partion(array,left,right,compareFunc)
local key = array[left]
local index = left
array[index],array[right] = array[right],array[index]
local i = left
while i< right do
if compareFunc( key,array[i]) then
array[index],array[i] = array[i],array[index]
index = index +
end
i = i +
end
array[right],array[index] = array[index],array[right]
return index;
end -- binary search
local function chash_find(point)
local mid, lo, hi = , , #CONTINUUM
while do
if point <= CONTINUUM[lo][] or point > CONTINUUM[hi][] then
return CONTINUUM[lo]
end -- test middle point
mid = lo + math.floor((hi-lo)/) -- perfect match
if point <= CONTINUUM[mid][] and point > (mid > and CONTINUUM[mid-][] or ) then
return CONTINUUM[mid]
end -- too low, go up
if CONTINUUM[mid][] < point then
lo = mid +
else
hi = mid -
end
end
end local function chash_init()
local n = #HASH_PEERS
if n == then
print("There is no backend servers")
return
end local C = {}
for i,peer in ipairs(HASH_PEERS) do
for k=, math.floor(VIRTUAL_NODE * peer[]) do
local hash_data = peer[] .. "-" .. (k - )
table.insert(C, {peer[], hash_fn(hash_data)})
end
end quicksort(C, function(a,b) return a[] > b[] end)
CONTINUUM = C --[[
for i=1,#C do
print(CONTINUUM[i][1],CONTINUUM[i][2])
end
--]] local step = math.floor(0xFFFFFFFF / CONSISTENT_BUCKETS) BUCKETS = {}
for i=, CONSISTENT_BUCKETS do
table.insert(BUCKETS, i, chash_find(math.floor(step * (i - ))))
-- print(BUCKETS[i][],BUCKETS[i][])
end end
M.init = chash_init local function chash_get_upstream_crc32(point)
return BUCKETS[(point % CONSISTENT_BUCKETS)+][]
end
M.get_upstream_crc32 = chash_get_upstream_crc32 local function chash_get_upstream(key)
local point = math.floor(hash_fn(key))
return chash_get_upstream_crc32(point)
end
M.get_upstream = chash_get_upstream local function chash_add_upstream(upstream, weigth)
weight = weight or
table.insert(HASH_PEERS, {weight, upstream})
end
M.add_upstream = chash_add_upstream return M
API调用方式:
local redis_login= {
"10.50.1.3:11211",
"10.50.1.4:11211",
"10.50.1.5:11211",
}
for k, backend in ipairs(redis_login) do
chash_login.add_upstream(backend)
end
chash_login.init()
uid=""
chash_login.chash_get_upstream(uid)
返回一个backend地址,将该uid对应的数据写入对应的redis中即可,稍后可以使用Nginx读到。
PS:关于redis的mass insertion问题,最高效的方式是批量写入文件(文件格式遵循redis协议),然后使用 redis-cli --pipe 直接导入。
Nginx一致性哈希模块的Lua实现的更多相关文章
- 018 nginx与第三模块整合[一致性哈希模块整合]
nginx第三方模块官网:http://wiki.nginx.org/HttpUpstreamConsistentHash nginx第三方模块下载地址:https://github.com/repl ...
- Nginx 第三方模块的安装以及一致性哈希算法的使用
Nginx 第三方模块的安装以及一致性哈希算法的使用 第三方模块安装方法总结: 以ngx_http_php_memcache_standard_balancer-master为例 1:解压 到 pat ...
- Nginx网络架构实战学习笔记(四):nginx连接memcached、第三方模块编译及一致性哈希应用
文章目录 nginx连接memcached 第三方模块编译及一致性哈希应用 总结 nginx连接memcached 首先确保nginx能正常连接php location ~ \.php$ { root ...
- Nginx的负载均衡 - 一致性哈希 (Consistent Hash)
Nginx版本:1.9.1 我的博客:http://blog.csdn.net/zhangskd 算法介绍 当后端是缓存服务器时,经常使用一致性哈希算法来进行负载均衡. 使用一致性哈希的好处在于,增减 ...
- OpenResty / Nginx模块,Lua库和相关资源的列表
OpenResty / Nginx模块,Lua库和相关资源的列表 什么是OpenResty OpenResty是一个成熟的网络平台,它集成了标准的Nginx核心,LuaJIT,许多精心编写的Lua库, ...
- nginx upstream一致性哈希的实现
地址:http://wiki.nginx.org/HttpUpstreamConsistentHash 首先声明一个命令: static ngx_command_t ngx_http_upstrea ...
- nginx系列12:一致性哈希算法
前面一节的hash算法存在一个问题,当上游的应用服务器因某一台down掉导致服务器数量发生变化时,会导致大量的请求路由策略失效,一致性哈希算法可以缓解这个问题. 一致性哈希算法 1,hash算法存在的 ...
- Nginx核心流程及模块介绍
Nginx核心流程及模块介绍 1. Nginx简介以及特点 Nginx简介: Nginx (engine x) 是一个高性能的web服务器和反向代理服务器,也是一个IMAP/POP3/SMTP服务器 ...
- .net的一致性哈希实现
最近在项目的微服务架构推进过程中,一个新的服务需要动态伸缩的弹性部署,所有容器化示例组成一个大的工作集群,以分布式处理的方式来完成一项工作,在集群中所有节点的任务分配过程中,由于集群工作节点需要动态增 ...
随机推荐
- 如何自定义kindeditor编辑器的工具栏items即去除不必要的工具栏或者保留部分工具栏
kindeditor编辑器的工具栏主要是指编辑器输入框上方的那些可以操作的菜单,默认情况下编辑器是给予了所有的工具栏.针对不同的用户,不同的项目,不同的环境,可能就需要保留部分工具栏.那么我们应该如何 ...
- OSGEARTH三维地形开源项目
第一章 OSGEarth介绍 第二章 OSGEarth编译环境配置 OSGEarth的编译环境配置随着版本的不同.运行平台的不同,也有很大的差异.本章主要以Windows XP SP3(x86 ...
- 【转】Python Twisted介绍
Python Twisted介绍 作者:Jessica McKellar 原文链接 Twisted是用Python实现的基于事件驱动的网络引擎框架.Twisted诞生于2000年初,在当时的网络游戏开 ...
- SVPullToRefresh 下拉刷新,上拉加载
https://github.com/Sephiroth87/ODRefreshControl 类似刷新控件,类似qq动画的那种刷新. 一.下载第三方库 https://github.com/samv ...
- HDU3923-Invoker-polya n次二面体
polya定理.等价类的个数等于∑颜色数^置换的轮换个数 不可翻转的串当中.直接计算∑m^(gcd(n,i)) ,这里gcd(n,i)就是第i个置换的轮换数. 翻转的情况再分n奇偶讨论. n次二面体都 ...
- Openwrt flash 空间不足的临时解决方法
最近有网友在安装软件的时候发现flash空间不够用了: 一个临时的解决方案是在RAM里面使用这个程序.因为 1.路由器改机后的RAM有64MB,flash一般有16MB,RAM空间比较大./tmp是挂 ...
- MFC中对话框类(Dialog)的应用
转载http://hi.baidu.com/jackywdx/item/feee8041d2c2e12310ee1e85 Windows应用程序通常是通过对话框接收用户输入.向用户输出信息,本节介绍应 ...
- HTML5 中canvas支持触摸屏的签名面板
1.前言 最近实在是太忙了,从国庆之后的辞职,在慢慢的找工作,到今天在现在的这家公司上班大半个月了,太多的心酸泪无以言表,面试过程中,见到的坑货公司是一家又一家,好几家公司自己都只是上一天班就走了,其 ...
- cookie的操作
比如这样如果一个网站上有两个域名的时候,我们需要考虑,两个域名下的cookie. 我们所说的跨域只的就是lesport.com和le.com js的cookie是不能跨域的,为了防止过大. js增加删 ...
- excel导入数据库
日常工作中,感觉一些基础知识需要做下笔记,可能是刚毕业的缘故吧,还保持着做笔记的习惯,但根据以往经验,纸质笔记最多保持一年,过后想找已是难过登天.电子版笔记感觉很不错,尤其是发布到网络中.笔记内容是本 ...