Redis integrates Lua script implementation and redislua script
Author: zhanhailiang Date: 2014-12-02
Related Dependencies
1. Environment deployment
- Redis installation and configuration tutorial and phpredis extension installation test
- Redis installation and php Extension
- Install the phpredis module in Windows (the php_redis.dll in the current Window environment is still 2.1.3, And the redis. so version in Linux has reached 2.2.5, which may lead to different degrees of support for some instruction sets)
2. Redis instruction manual
- Php-redis Chinese help manual. chm (this manual is relatively old, please refer to Redis Commands)
- Redis Commands
- EVAL script numkeys key [key...] arg [arg...]
3. Lua language basics
- Lua 5.1 Reference Manual
- Lua table traversal Array application
4. communication principle between Redis and Lua
- Lua: getting started with Redis users
- New Redis branch for development supported by server lua script
- Redis 2.6 Lua Script Function Implementation Analysis
Advantages of integrating Lua scripts to operate Redis
Faster access to Redis! Many Redis applications use the read-compute-write mode, which requires two communications between the client and the server for a simple data computation, if the intermediate compute process is transferred to the server for execution, the round-trip time can be multiplied.
Make full use of CPU! The vast majority of Redis application scenarios are IO-intensive. Even when the CPU reaches the limit (Redis cannot use multiple cores), most of the CPU usage is on the processing of the network protocol stack, however, if the script executed by the Server is used, the CPU of the Redis Server can be fully utilized.
But the most fundamental reason is that we can only implement the most basic functions in Redis to meet the needs of 99% users, leave 1% of the functions in other unique application scenarios to the custom server execution script for implementation. If you are afraid that Redis will become redundant after the server script is introduced, you can take a sigh of relief, because this is the ultimate solution proposed to prevent endless demands.
For the original article, see the new Redis branch for development supported by the server lua script.
Disadvantages of Lua script integration (to be verified)
- When twemproxy is used as the redis svr proxy, some compatibility problems may occur because twemproxy does not fully support eval and evalSha;
- Lua may overhead the server;
Application Principle
Redis communicates with Lua scripts by sending the lua script as a command to the server. The server reads the script, calls the interpreter to explain the script, and runs the script and returns it.
It provides two interfaces:
[root@~/wade/lua/historyBrowsing]# redis-cli 127.0.0.1:6379> help eval EVAL script numkeys key [key ...] arg [arg ...] summary: Execute a Lua script server side since: 2.6.0 group: scripting 127.0.0.1:6379> help evalsha EVALSHA sha1 numkeys key [key ...] arg [arg ...] summary: Execute a Lua script server side since: 2.6.0 group: scripting
Next, we will explain the application scenarios through a simple Demo:
A data key named name2 is stored on the redis server, and its storage structure is zset. In this case, we can access the data using the following method:
127.0.0.1:6379> eval 'return redis.call("zrange", "name2", 0 , -1);' 01) "1"
Of course, the above example is only for eval usage. In actual operation, you can directly use redis-client zrang name2 0-1.
However, if I want to dynamically read the key to obtain the corresponding value, we need to use the lua script to implement the corresponding function.
The code hosted on github.com allows you to add browsing history. If you are interested, you can learn how to communicate with lua without worrying about the specific business logic:
<? Php // vim: set expandtab cindent tabstop = 4 shiftwidth = 4 OFDM = marker: /*** @ version 1.0 * @ author wade * @ date 2014-12-01 22:56:38 * @ desc redis integrates the lua Script Function to implement browsing history */$ redis = new Redis (); $ redis-> connect ('2017. 0.0.1 ', '000000'); // $ redis-> set ('test', 'Hello World'); // echo $ redis-> get ('test '); $ luasts = file_get_contents ('. /addItemToBrowsingHistory. lua'); $ ret = $ redis-> eval ($ luasloud, array (4028, 'brand _ browsing_10010 ', 1417498107, 'brand _ expired_10010', 1417498107,141 7498107, 3, (1417457308); var_export ($ ret); $ err = $ redis-> getLastError (); var_export ($ err );
-- $ ProductId, $ browsingKey, $ browsingTime, $ expiredKey, $ expiredTime, $ delTime, $ maxHistoryLength, $ now -- ARGV [1], ARGV [2], ARGV [3], ARGV [4], ARGV [5], ARGV [6], ARGV [7], ARGV [8] -- 4011, brand_browsing_10010, 1417498107, brand_expired_10010, 1417498107,141 7498107, 3, 1417440107 local productId = ARGV [1]; local browsingKey = ARGV [2]; local browsingTime = ARGV [3]; local expiredKey = ARGV [4]; local expi RedTime = ARGV [5]; local delTime = ARGV [6]; local maxHistoryLength = ARGV [7]; local now = ARGV [8]; local num; local tProductId; local index; redis. call ('zadd', browsingKey, browsingTime, productId); redis. call ('expire ', browsingKey, delTime); redis. call ('zadd', expiredKey, expiredTime, productId); redis. call ('expire ', expiredKey, delTime); local count = redis. call ('zcard', expiredKey); local balance = coun T-maxHistoryLength; if balance> 0 then -- get the expiration list -- NMB by score local expiredList = redis. call ('zrangebyscore ', expiredKey, 0, now); if expiredList ~ = False and # expiredList ~ = 0 then -- deleted num = redis when the product expires. call ('zdeleterangebyscore ', expiredKey, 0, now); balance = balance-num; for tProductId in ipairs (expiredList) do redis. call ('zrem ', browsingKey, tProductId); end if balance> 0 then -- otherwise, judge the browsing history list -- delete the browsing history. Last, the local expiredList2 = redis. call ('zrange', browsingKey, 0, balance-1); num = redis. call ('zremrangebyrank ', browsingKey, 0, balance-1); -- NMB by index for index = 1, # expiredList2 do redis. call ('zrem ', expiredKey, expiredList2 [index]); end endend return 0;
See the source code: https://github.com/billfeller/historyBrowsing