某手机应用市场项目,其中请求量最大的功能是查询升级接口,具体点来说:客户端会不定期的把手机中应用名称及其应用版本发送到服务端,服务端通过比较版本来判断客户端的应用是否需要升级,如果需要就返回若干项相关信息。通常,一台手机里会装几十个到上百
某手机应用市场项目,其中请求量最大的功能是查询升级接口,具体点来说:客户端会不定期的把手机中应用名称及其应用版本发送到服务端,服务端通过比较版本来判断客户端的应用是否需要升级,如果需要就返回若干项相关信息。通常,一台手机里会装几十个到上百个应用不等,当海量客户端一起请求时,服务端的压力可想而知。
客户端请求的数据格式如下所示,可以采用GET或POST方法:
packages=foo|1&packages=bar|2&packages=<name>|<version>&...</version></name>
服务端选择Lua作为编程语言,同时利用了Redis的PIPELINING机制批量查询数据:
local redis = require "resty.redis" local cjson = require "cjson" local config = require "config" ngx.header["Content-Type"] = "application/json; charset=utf-8" local args = ngx.req.get_uri_args(1000) if ngx.var.request_method == "POST" then ngx.req.read_body() for key, val in pairs(ngx.req.get_post_args(1000)) do args[key] = val end end if type(args["packages"]) == "string" then args["packages"] = {args["packages"]} end if type(args["packages"]) ~= "table" then ngx.exit(ngx.HTTP_BAD_REQUEST) end local cache = redis.new() local res, err = cache:connect(config.host, config.port) if not res then ngx.log(ngx.ERR, "error: ", err) ngx.exit(ngx.HTTP_SERVICE_UNAVAILABLE) end cache:init_pipeline() local packages = {} for _, val in ipairs(args["packages"]) do if type(val) == "string" then local name, version = string.match(val, "([^|]+)|([0-9]+)") if name and version then packages[name] = tonumber(version) cache:hget(name, "all") end end end local res, err = cache:commit_pipeline() if not res then ngx.log(ngx.ERR, "error: ", err) ngx.exit(ngx.HTTP_SERVICE_UNAVAILABLE) end local data = {} for _, val in ipairs(res) do if type(val) == "string" then val = cjson.decode(val) if packages[val["name"]] <p>补充:应用的数据作为HASH保存在Redis里,不过由于HGETALL非常耗费CPU,所以做了些处理:冗余保存了一个名为「all」的字段,用来保存原始数据的JSON编码,如此一来,就把复杂度为O(N)的HGETALL操作转化成了复杂度为O(1)的HGET操作,从而提升了效率。详细介绍请参考:《记Redis那坑人的HGETALL》。</p> <p>如上代码平稳运行了一段时间,但随着访问量的增加,开始暴露问题:Redis时不时出现卡住的现象,究其原因就是单线程的Redis无法承载过大的PIPELINING请求。通常我们都是采用多实例的方法来规避Redis单线程的性能瓶颈问题,但在本例中,由于PIPELING很大,不是随便冗余几个实例就能解决问题,同时系统也没有太多的内存可用。</p> <p>最后我们想到的办法是利用Nginx/Lua给Redis的PIPELINING减肥,具体一点来说:当客户端查询升级接口时,虽然会把多至上百个应用的信息同时发送到服务端,但其中真正升级的应用却很少,如果我们能把那些不升级的应用过滤掉,只查询升级的应用,无疑将大大提升系统的性能,形象一点说:当一个胖子请求经过过滤后,就变成了一个瘦子请求。实际操作时,我们可以把应用的版本缓存到Nginx/Lua共享内存里,客户端请求先在Nginx/Lua共享内存过滤一次,然后再判断是否需要查询Redis。</p> <p>为了使用共享内存,需要在Nginx配置文件中声明:</p> <pre class="brush:php;toolbar:false">lua_shared_dict versions 100m;
改良后的代码如下所示,注意其中共享内存的查询和设置部分的代码:
local redis = require "resty.redis" local cjson = require "cjson" local config = require "config" local versions = ngx.shared.versions; ngx.header["Content-Type"] = "application/json; charset=utf-8" local args = ngx.req.get_uri_args(1000) if ngx.var.request_method == "POST" then ngx.req.read_body() for key, val in pairs(ngx.req.get_post_args(1000)) do args[key] = val end end if type(args["packages"]) == "string" then args["packages"] = {args["packages"]} end if type(args["packages"]) ~= "table" then ngx.exit(ngx.HTTP_BAD_REQUEST) end local cache = redis.new() local res, err = cache:connect(config.host, config.port) if not res then ngx.log(ngx.ERR, "error: ", err) ngx.exit(ngx.HTTP_SERVICE_UNAVAILABLE) end cache:init_pipeline() local packages = {} for _, val in ipairs(args["packages"]) do if type(val) == "string" then local name, version = string.match(val, "([^|]+)|([0-9]+)") if name and version then version = tonumber(version) if not versions[name] or versions[name] > version then packages[name] = version cache:hget(name, "all") end end end end local res, err = cache:commit_pipeline() if not res then ngx.log(ngx.ERR, "error: ", err) ngx.exit(ngx.HTTP_SERVICE_UNAVAILABLE) end local data = {} for _, val in ipairs(res) do if type(val) == "string" then val = cjson.decode(val) if packages[val["name"]] <p>或许会有人会质疑:本质上请求量并没有减少啊,只是从Redis转嫁到了Nginx而已,这样就能提升性能么?问题的关键在于Redis是单线程的,而Nginx通过worker_processes指令,可以充分发挥多核CPU的能力,所以性能总体是提升的。</p> <p>补充:代码里在设置共享内存过期时间的时候,没有采用固定值,而是采用了一个随机数的方式,之所以这样设计,是为了避免大量数据同时过期,系统性能出现抖动。</p> <p>…</p> <p>当然,随着访问量的增加,本文的方案可能还会出现问题,到时候怎么办呢?其实类似查询升级之类的功能,就不应该设计成同步的形式,如果能改成异步的方式,那么多数问题就都不存在了,不过这个就不多言了,现在的方案刚刚好够用。</p> <p class="copyright"> 原文地址:通过Nginx/Lua给Redis的PIPELINING减肥, 感谢原作者分享。 </p>

MySQLデータベースをアップグレードする手順には次のものがあります。1。データベースをバックアップします。2。現在のMySQLサービスを停止します。3。MySQLの新しいバージョンをインストールします。アップグレードプロセス中に互換性の問題が必要であり、Perconatoolkitなどの高度なツールをテストと最適化に使用できます。

MySQLバックアップポリシーには、論理バックアップ、物理バックアップ、増分バックアップ、レプリケーションベースのバックアップ、クラウドバックアップが含まれます。 1. Logical BackupはMySqldumpを使用してデータベースの構造とデータをエクスポートします。これは、小さなデータベースとバージョンの移行に適しています。 2.物理バックアップは、データファイルをコピーすることで高速かつ包括的ですが、データベースの一貫性が必要です。 3.インクリメンタルバックアップは、バイナリロギングを使用して変更を記録します。これは、大規模なデータベースに適しています。 4.レプリケーションベースのバックアップは、サーバーからバックアップすることにより、生産システムへの影響を減らします。 5. Amazonrdsなどのクラウドバックアップは自動化ソリューションを提供しますが、コストと制御を考慮する必要があります。ポリシーを選択するときは、データベースサイズ、ダウンタイム許容度、回復時間、および回復ポイントの目標を考慮する必要があります。

mysqlclusteringenhancesdatabaserobustnessnessnessnessnessnistandistributiondistributingdataacrossmultiplenodes.itesthendbenginefordatareplication andfaulttolerance、保証highavailability.setupinvolvesconfiguringmanagement、data、ssqlnodes、carefulmonitoringringandpe

MySQLのデータベーススキーマ設計の最適化は、次の手順を通じてパフォーマンスを改善できます。1。インデックス最適化:一般的なクエリ列にインデックスを作成し、クエリのオーバーヘッドのバランスをとり、更新を挿入します。 2。テーブル構造の最適化:正規化または反通常化によりデータ冗長性を削減し、アクセス効率を改善します。 3。データ型の選択:Varcharの代わりにINTなどの適切なデータ型を使用して、ストレージスペースを削減します。 4。パーティション化とサブテーブル:大量のデータボリュームの場合、パーティション化とサブテーブルを使用してデータを分散させてクエリとメンテナンスの効率を改善します。

tooptimizemysqlperformance、soflowthesesteps:1)properindexingtospeedupqueries、2)useexplaintoanalyzeandoptimize Queryperformance、3)AductServerContingSettingStingsinginginnodb_buffer_pool_sizeandmax_connections、4)

MySQL関数は、データ処理と計算に使用できます。 1.基本的な使用には、文字列処理、日付計算、数学操作が含まれます。 2。高度な使用法には、複数の関数を組み合わせて複雑な操作を実装することが含まれます。 3.パフォーマンスの最適化では、Where句での機能の使用を回避し、GroupByおよび一時テーブルを使用する必要があります。

MySQLでデータを挿入するための効率的な方法には、次のものが含まれます。1。insertInto ...値構文、2。LoadDatainFileコマンドの使用、3。トランザクション処理の使用、4。バッチサイズの調整、5。Insurtignoreまたは挿入の使用...

MySQLでは、AlterTabletable_nameaddcolumnnew_columnvarchar(255)afterexisting_columnを使用してフィールドを追加し、andtabletable_namedopcolumncolumn_to_dropを使用してフィールドを削除します。フィールドを追加するときは、クエリのパフォーマンスとデータ構造を最適化する場所を指定する必要があります。フィールドを削除する前に、操作が不可逆的であることを確認する必要があります。オンラインDDL、バックアップデータ、テスト環境、および低負荷期間を使用したテーブル構造の変更は、パフォーマンスの最適化とベストプラクティスです。


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

SublimeText3 Linux 新バージョン
SublimeText3 Linux 最新バージョン

VSCode Windows 64 ビットのダウンロード
Microsoft によって発売された無料で強力な IDE エディター

ドリームウィーバー CS6
ビジュアル Web 開発ツール

Dreamweaver Mac版
ビジュアル Web 開発ツール

WebStorm Mac版
便利なJavaScript開発ツール

ホットトピック









