redis统计大key

redis的–bigkeys参数:对redis整个keyspace进行统计(数据量大时采样,调用scan命令),寻找每种数据类型较大的keys,给出数据统计

redis-cli –bigkeys -i 0.1 -h 127.0.0.1

golang基于redis lua封装的优先级去重队列

前言:

 前两天由于某几个厂商的api出问题,导致后台任务大量堆积,又因为我这边任务流系统会重试超时任务,所以导致队列中有大量的重复任务。这时候我们要临时解决两个事情,一件事情,让一些高质量的任务优先执行; 另一件事情, 要有去重。 rabbitmq不能很好的针对这类情况去重、分优先级。  

 这时候我又想到了我最爱的redis…   去重?  list + set 就可以解决, 优先级,zset + zrange + zrem 也可以解决…  但问题这几个命令非原子,那么怎么让他们原子?   写模块 or redis lua script .   首先在 redis 4.x 写了个简单的module,但写完了发现一件颇为重要的事情,我们线上的是3.2 ….  然后又花了点时间改成redis lua的版本。项目本身的功能实现很简单,复杂的是创意 !!! 

项目名: redis_unique_queue, 项目地址,https://github.com/rfyiamcool/redis_unique_queue

主要功能介绍:

使用redis lua script 封装的去重及优先级队列方法, 达到了组合命令的原子性和节省来往的io请求的目的.

去重队列:

不仅能保证FIFO, 而且去重.

优先级去重队列:

按照优先级获取任务, 并且去重.

使用方法:

# xiaorui.cc

PriorityQueue

NewPriorityQueue(priority int, unique bool, r *redis.Pool)

Push(q string, body string, pri int) (int, error)

Pop(q string) (resp string, err error)
UniqueQueue

NewUniqueQueue(r *redis.Pool) *UniqueQueue

UniquePush(q string, body string) (int, error)

UniquePop(q string) (resp string, err error)

more..

下面是优先级去重队列的例子:

package main

// xiaorui.cc

import (
    "fmt"

    "github.com/rfyiamcool/redis_unique_queue"
)

func main() {
    fmt.Println("start")
    redis_client_config := unique_queue.RedisConfType{
        RedisPw:          "",
        RedisHost:        "127.0.0.1:6379",
        RedisDb:          0,
        RedisMaxActive:   100,
        RedisMaxIdle:     100,
        RedisIdleTimeOut: 1000,
    }
    redis_client := unique_queue.NewRedisPool(redis_client_config)

    qname := "xiaorui.cc"
    body := "message from xiaorui.cc"

    u := unique_queue.NewPriorityQueue(3, true, redis_client)
    // 3: 3个优先级,从1-3级
    // true: 开启unique set

    u.Push(qname, body, 2)
    // 2, 优先级

    fmt.Println(u.Pop(qname))
}

单单使用 去重队列的例子:

package main

import (
    "fmt"

    "github.com/rfyiamcool/redis_unique_queue"
)

func main() {
    fmt.Println("start")
    redis_client_config := unique_queue.RedisConfType{
        RedisPw:          "",
        RedisHost:        "127.0.0.1:6379",
        RedisDb:          0,
        RedisMaxActive:   100,
        RedisMaxIdle:     100,
        RedisIdleTimeOut: 1000,
    }
    redis_client := unique_queue.NewRedisPool(redis_client_config)


    qname := "xiaorui.cc"
    u := unique_queue.NewUniqueQueue(redis_client)
    for i := 0; i < 100; i++ {
        u.UniquePush(qname, "body...")
    }

    fmt.Println(u.Length(qname))

    for i := 0; i < 100; i++ {
        u.UniquePop(qname)
    }

    fmt.Println(u.Length(qname))


    fmt.Println("end")
}

需要改进地址也是很多, 比如 加入批量操作, 对于redis连接池引入方法改进等.

END.

redis批量删除key

最近生产环境的redis服务器由于key过期不及时,现在发现时key的个数已经暴增到5000多万了。然后运维同学那边就报警了,最大内存12G,已经用了9G多了,正好下面快要双11了,让我们快些解决。

redis服务器里面堆积大量的队列状态相关的key,其实这些key可以设置有效期,或者任务完成以后删除或者过期,但是由于我们使用类库的问题,这些key既没有删除也没有过期,堆积到redis里面去了,现在我们要做的就是删除这些无用key。在删除这些keys的过程中,走了不少弯路,这里说一下我最终采用的方案。

redis的del函数可以删除单个key,也可以删除多个key,del函数官方文档可以看这里。在google之后看到目前网络上很多文章的思路是使用keys匹配返回要删除的key,然后调用del函数去删除。这种方案在数据量较小时无可厚非,但如果像我这样面临的处理的数据有5千W时,keys的阻塞问题可能会给线上生产环境带来致命的问题。所以我们需要对这种方案作出一些修改。

可喜的是自从2.8.0以后redis提供scan来遍历key,而且这个过程是非阻塞,不会影响线上生产环境。最终经过修改的方案是用scan遍历要删除的key,然后调用del删除。

下面是我用python写的用来删除key的脚本。

import sys,redis

r = redis.Redis(host="127.0.0.1", port=6379,db=0)

if  len(sys.argv) <= 1:
    print("必须指明匹配key字符串")
    exit(1)
pattern = sys.argv[1]

cursor = 0
num = 1
while 1 :
    resut = r.scan(cursor, pattern, 10000)
    del_keys = []
    for i in resut[1]:
        key = i.decode()
        del_keys.append(key)
    #print("del keys len :%d" % len(result))
    if len(del_keys) == 0:
        break
    r.delete(*del_keys)
    cursor = resut[0]
    print("delete keys num : %dw" % (num))
    num +=1

print("donen")

如何利用我这个脚本删除符合某个规则的key哪,如以king开头的key?

下面的命令即可完成上面的问题。

python3 main.py "king*"

期间我看到网上利用keys+del的lua脚本的方案,花了一段时间把scan+del改成lua脚本来删除。但是可惜的是目前redis并不支持这么做,由于scan返回的结果是不确定的,所以禁止在其后直接调用del操作。

使用docker的redis镜像

前言

docker的官方镜像提供了redis的镜像,为了方便自己随时随地需要的使用,就学习一下,顺便记录下来。

参考Docker官方Redis镜像: https://hub.docker.com/_/redis/

准备工作

  • 一台linux机器(我用windows10自带的hyper-v装了个虚拟机)
  • 安装docker

获取redis镜像

一行命令搞定:

$> docker pull redis

说明: docker的官方镜像都可以在Docker Hub上找到,这里会自动从Docker Hub 上找到对应的镜像并下载。

下载完成之后,可以使用如下命令查看镜像:

$> docker images

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
redis               latest              1fb7b6c8c0d0        6 days ago          107MB (1)
oraclelinux         latest              6c33a25f4a29        2 weeks ago         229MB
elasticsearch       latest              d1ac13423d3c        5 weeks ago         580MB
hello-world         latest              1815c82652c0        4 months ago        1.84kB

这个就是我们刚刚获取的镜像。

运行redis镜像

$> docker run --name my-redis -d redis
7dabbc56e3514e9ba1705d6c6ec180e603ceff7e6011f7915ef3b0f1f5b05b35

启动后可以查看redis运行的信息:

$> docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
7dabbc56e351        redis               "docker-entrypoint..."   35 minutes ago      Up 35 minutes       6379/tcp            my-redis

连接redis

在虚拟机中,没有ui工具可以连接redis,要测试redis是否正常服务,需要安装redis的命令行客户端工具(redis-cli)。

安装redis-cli

$> wget http://download.redis.io/releases/redis-2.8.17.tar.gz
$> tar xzf redis-2.8.17.tar.gz
$> cd redis-2.8.17
$> make

注意: 这里是下载redis源码进行编译,编译后在src目录下就会有redis-cli工具。 源码编译过程需要使用gcc,如果没有安装的话请先用yum或者apt-get安装gcc。 如:yum install gcc或apt-get install gcc。

编译完成后:

$> cd src
$> ./redis-cli
Could not connect to Redis at 127.0.0.1:6379: Connection refused
not connected> 

说明已经编译完成,可以使用了。

由于没有参数的情况下,默认是连接127.0.0.1:6379,这里连接失败了,先退出cli:

not connected> exit

连接docker-redis

现在我们需要知道docker中的redis的IP地址:

$> docker inspect --format '' ${容器id}

容器id我们前面已经用docker ps看到了,拷贝过来替换掉${容器id}。

$> docker inspect --format '' 7dabbc56e351
172.17.0.2

连接:

$> ./redis-cli -h 172.17.0.2
172.17.0.2:6379> 

不需要指定端口,使用默认端口6379即可。

正常连接上了,现在测试一下:

172.17.0.2:6379> set first:key "hello redis"
OK
172.17.0.2:6379> get first:key
"hello redis"
172.17.0.2:6379> 

成功!

允许物理机连接

上面成功连接之后,说明我们已经可以正常使用redis了,但是实际上这不是我们想要的效果,因为只能在虚拟机内连接,我们希望可以在物理机上连接,这样才可以进行开发。

现在让我们先停掉虚拟机里的dcoker:

$> docker stop ${容器id}

现在重新启动docker的redis镜像,同时指定主机端口映射容器端口:

$> docker run -p 6379:6379 --name port-map-redis -d redis

现在使用redis-cli直接连接本地:

$> ./redis-cli
127.0.0.1:6379>

说明连接本地成功。

Linux下Redis服务器搭建

一、系统环境

  • 操作系统:CentOS 6.9

  • redis版本:redis-4.0.2

二、安装步骤

1. 安装预环境

运行以下命令安装预环境。

[root@redis02 redis-4.0.2]# yum -y install gcc make

2. 下载redis源代码文件并解压缩

下载完redis源代码后,运行以下命令进行解压缩。

[root@redis02 softwares]# tar -xzf redis-4.0.2.tar.gz

未分类

3. redis编译

运行make命令进行编译。

未分类

make命令执行完成编译后,会在src目录下生成6个可执行文件,分别是redis-server、redis-cli、redis-benchmark、redis-check-aof、redis-check-dump、redis-sentinel。

4. redis安装配置

运行make install命令。

未分类

命令执行后会将make编译生成的可执行文件拷贝到/usr/local/bin目录下,如下图。

未分类

然后,运行./utils/install_server.sh配置向导来配置redis,并且可以将redis服务加到开机自启动中。【重要】

未分类

5. redis服务查看,开启和关闭

此时redis服务已经启动了。可以通过以下命令来操作redis了。

查看redis的运行状态:

[root@redis02 redis-4.0.2]# service redis_6379 status

关闭redis服务:

[root@redis02 redis-4.0.2]# service redis_6379 stop

开启redis服务:

[root@redis02 redis-4.0.2]# service redis_6379 start

最后可以通过redis内置的客户端工具来测试下:

[root@redis02 ~]# redis-cli
127.0.0.1:6379> get name

(nil)

127.0.0.1:6379> set name mcgrady

OK

127.0.0.1:6379> get name

"mcgrady"

127.0.0.1:6379>

可以看到,redis服务已经成功配置好了!

三、注意事项

1. 运行make命令报错?

错误信息如下:

make[3]: gcc: Command not found

/bin/sh: cc: command not found

解决方案:

因为预环境没有安装,运行以下命令安装预环境。

[root@redis02 redis-4.0.2]# yum -y install gcc make

2. 安装完预环境后运行make命令报以下错误?

错误信息:

zmalloc.h:50:31: error: jemalloc/jemalloc.h: No such file or directory

zmalloc.h:55:2: error: #error "Newer version of jemalloc required"

解决方案:

运行以下命令。

make MALLOC=libc

3. 运行make test命令报以下错误?

错误信息:

You need tcl 8.5 or newer in order to run the Redis test

解决方案:

运行以下命令安装tcl。

[root@redis02 redis-4.0.2]# yum -y install tcl

4. 调用ConnectionMultiplexer.Connect创建连接的时候报错?

错误信息:

It was not possible to connect to the redis server(s); to create a disconnected multiplexer, disable AbortOnConnectFail. UnableToResolvePhysicalConnection on TIME

解决方案:

1)关闭保护模式,注意默认是打开的。

未分类

2)绑定IP,注意默认只绑定了127.0.0.1。

未分类

有用命令:

telnet 192.168.1.29 6379,可以直接测试客户端是否能连上服务器,如果通的话,基本上就没有什么问题。

ps -aux | grep redis ,查看redis的进程,看redis是否正常启动。

Redis 乐观锁

乐观锁大多是以数据版本号来进行成功或者失败!

举个例子:

假设某个文章的点赞数为100,此时的version我们暂定没有异常为100.

当用户A对他进行点赞的时候进行操作,那此时的点赞数为100+1、version=101,提交更新时,由于版本号大于数据库记录的版本号,数据被更新,此时数据记录的version=101。

然而在特殊情况下用户B是和用户A是同时进行操作的,也就是说,他获得的version也是100、点赞数为100,提交结果是点赞数为100+1、version=101,但是此时对数据库的版本发现当前数据记录的version也为101,不满足当前提交版本号大于数据库版本号,所以此时更新操作被驳回。

执行实验代码:

WATCH test

value = GET test

value = value+1

MULTI

SET test value

EXEC

由于WATCH 的key会被监视,会校验这个key是否被更改,如果该监视的key 在EXEC执行前被修改了,那么整个事务都会被驳回。

php实现代码

$redis = new redis();  
$redis->connect('127.0.0.1', 6379);  
//获取当前点赞数 
$test = $redis->get("test");  
$count = 1;   //默认每次点赞+1  

$redis->watch("test");  
$redis->multi();  
//设置延迟,方便测试效果。  
sleep(5);  
//插入抢购数据  
$redis->set("test",$test+$count);  
$res = $redis->exec();  
if($res){  
    $new_test = $redis->get("test");  
    echo "点赞成功当前点赞数为:".$new_test."<br/>";  
}else{  
    echo "点赞失败";exit;  
}  

需要注意的是如果使用同一个浏览器的多个标签页同时访问同一个URL,那么浏览器认为这些不同的请求是同一个人,会对你的每个请求进行排队,不做并发处理。不管Nginx还是Apache,都是在并发处理,只不过你的浏览器自作主张,把你的请求阻塞了。

Redis分布式锁解决抢购问题

废话不多说,首先分享一个业务场景-抢购。一个典型的高并发问题,所需的最关键字段就是库存,在高并发的情况下每次都去数据库查询显然是不合适的,因此把库存信息存入Redis中,利用redis的锁机制来控制并发访问,是一个不错的解决方案。

首先是一段业务代码:

@Transactional
public void orderProductMockDiffUser(String productId){
    //1.查库存
    int stockNum  = stock.get(productId);
    if(stocknum == 0){
        throw new SellException(ProductStatusEnum.STOCK_EMPTY);
        //这里抛出的异常要是运行时异常,否则无法进行数据回滚,这也是spring中比较基础的   
    }else{
        //2.下单
        orders.put(KeyUtil.genUniqueKey(),productId);//生成随机用户id模拟高并发
        sotckNum = stockNum-1;
        try{
            Thread.sleep(100);
        } catch (InterruptedExcption e){
            e.printStackTrace();
        }
        stock.put(productId,stockNum);
    }
}

这里有一种比较简单的解决方案,就是synchronized关键字。

public synchronized void orderProductMockDiffUser(String productId)

这就是java自带的一种锁机制,简单的对函数加锁和释放锁。但问题是这个实在是太慢了,感兴趣的可以可以写个接口用apache ab压测一下。

ab -n 500 -c 100 http://localhost:8080/xxxxxxx

下面就是redis分布式锁的解决方法。首先要了解两个redis指令
SETNX 和 GETSET,可以在redis中文网上找到详细的介绍。
SETNX就是set if not exist的缩写,如果不存在就返回保存value并返回1,如果存在就返回0。
GETSET其实就是两个指令GET和SET,首先会GET到当前key的值并返回,然后在设置当前Key为要设置Value。

首先我们先新建一个RedisLock类:

@Slf4j
@Component
public class RedisService {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;


    /***
     * 加锁
     * @param key
     * @param value 当前时间+超时时间
     * @return 锁住返回true
     */
    public boolean lock(String key,String value){
        if(stringRedisTemplate.opsForValue().setIfAbsent(key,value)){//setNX 返回boolean
            return true;
        }
        //如果锁超时 ***
        String currentValue = stringRedisTemplate.opsForValue().get(key);
        if(!StringUtils.isEmpty(currentValue) && Long.parseLong(currentValue)<System.currentTimeMillis()){
            //获取上一个锁的时间
            String oldvalue  = stringRedisTemplate.opsForValue().getAndSet(key,value);
            if(!StringUtils.isEmpty(oldvalue)&&oldvalue.equals(currentValue)){
                return true;
            }
        }
        return false;
    }
    /***
     * 解锁
     * @param key
     * @param value
     * @return
     */
    public void unlock(String key,String value){
        try {
            String currentValue = stringRedisTemplate.opsForValue().get(key);
            if(!StringUtils.isEmpty(currentValue)&&currentValue.equals(value)){
                stringRedisTemplate.opsForValue().getOperations().delete(key);
            }
        } catch (Exception e) {
            log.error("解锁异常");
        }
    }
}

这个项目是springboot的项目。首先要加入redis的pom依赖,该类只有两个功能,加锁和解锁,解锁比较简单,就是删除当前key的键值对。我们主要来说一说加锁这个功能。

首先,锁的value值是当前时间加上过期时间的时间戳,Long类型。首先看到用setiFAbsent方法也就是对应的SETNX,在没有线程获得锁的情况下可以直接拿到锁,并返回true也就是加锁,最后没有获得锁的线程会返回false。 最重要的是中间对于锁超时的处理,如果没有这段代码,当秒杀方法发生异常的时候,后续的线程都无法得到锁,也就陷入了一个死锁的情况。我们可以假设CurrentValue为A,并且在执行过程中抛出了异常,这时进入了两个value为B的线程来争夺这个锁,也就是走到了注释*的地方。currentValue==A,这时某一个线程执行到了getAndSet(key,value)函数(某一时刻一定只有一个线程执行这个方法,其他要等待)。这时oldvalue也就是之前的value等于A,在方法执行过后,oldvalue会被设置为当前的value也就是B。这时继续执行,由于oldValue==currentValue所以该线程获取到锁。而另一个线程获取的oldvalue是B,而currentValue是A,所以他就获取不到锁啦。多线程还是有些乱的,需要好好想一想。

接下来就是在业务代码中加锁啦:首要要@Autowired注入刚刚RedisLock类,不要忘记对这个类加一个@Component注解否则无法注入

private static final int TIMEOUT= 10*1000;
@Transactional
public void orderProductMockDiffUser(String productId){
     long time = System.currentTimeMillions()+TIMEOUT;
   if(!redislock.lock(productId,String.valueOf(time)){
    throw new SellException(101,"换个姿势再试试")
    }
    //1.查库存
    int stockNum  = stock.get(productId);
    if(stocknum == 0){
        throw new SellException(ProductStatusEnum.STOCK_EMPTY);
        //这里抛出的异常要是运行时异常,否则无法进行数据回滚,这也是spring中比较基础的   
    }else{
        //2.下单
        orders.put(KeyUtil.genUniqueKey(),productId);//生成随机用户id模拟高并发
        sotckNum = stockNum-1;
        try{
            Thread.sleep(100);
        } catch (InterruptedExcption e){
            e.printStackTrace();
        }
        stock.put(productId,stockNum);
    }
    redisLock.unlock(productId,String.valueOf(time));
}

大功告成了!比synchronized快了不知道多少倍,再也不会被老板骂了!

Redis与Memcached的区别

传统MySQL+ Memcached架构遇到的问题
  
实际MySQL是适合进行海量数据存储的,通过Memcached将热点数据加载到cache,加速访问,很多公司都曾经使用过这样的架构,但随着业务数据量的不断增加,和访问量的持续增长,我们遇到了很多问题:

  1. MySQL需要不断进行拆库拆表,Memcached也需不断跟着扩容,扩容和维护工作占据大量开发时间。
      
  2. Memcached与MySQL数据库数据一致性问题。
      
  3. Memcached数据命中率低或down机,大量访问直接穿透到DB,MySQL无法支撑。
      
  4. 跨机房cache同步问题。

众多NoSQL百花齐放,如何选择
  
最近几年,业界不断涌现出很多各种各样的NoSQL产品,那么如何才能正确地使用好这些产品,最大化地发挥其长处,是我们需要深入研究和思考的问题,实际归根结底最重要的是了解这些产品的定位,并且了解到每款产品的tradeoffs,在实际应用中做到扬长避短,总体上这些NoSQL主要用于解决以下几种问题

  1. 少量数据存储,高速读写访问。此类产品通过数据全部in-momery 的方式来保证高速访问,同时提供数据落地的功能,实际这正是Redis最主要的适用场景。
      
  2. 海量数据存储,分布式系统支持,数据一致性保证,方便的集群节点添加/删除。
      
  3. 这方面最具代表性的是dynamo和bigtable 2篇论文所阐述的思路。前者是一个完全无中心的设计,节点之间通过gossip方式传递集群信息,数据保证最终一致性,后者是一个中心化的方案设计,通过类似一个分布式锁服务来保证强一致性,数据写入先写内存和redo log,然后定期compat归并到磁盘上,将随机写优化为顺序写,提高写入性能。
      
  4. Schema free,auto-sharding等。比如目前常见的一些文档数据库都是支持schema-free的,直接存储json格式数据,并且支持auto-sharding等功能,比如mongodb。

面对这些不同类型的NoSQL产品,我们需要根据我们的业务场景选择最合适的产品。
  
Redis适用场景,如何正确的使用
  
前面已经分析过,Redis最适合所有数据in-momory的场景,虽然Redis也提供持久化功能,但实际更多的是一个disk-backed的功能,跟传统意义上的持久化有比较大的差别,那么可能大家就会有疑问,似乎Redis更像一个加强版的Memcached,那么何时使用Memcached,何时使用Redis呢?

如果简单地比较Redis与Memcached的区别,大多数都会得到以下观点:

  1. Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储。

  2. Redis支持数据的备份,即master-slave模式的数据备份。

  3. Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。

抛开这些,可以深入到Redis内部构造去观察更加本质的区别,理解Redis的设计。

在Redis中,并不是所有的数据都一直存储在内存中的。这是和Memcached相比一个最大的区别。Redis只会缓存所有的 key的信息,如果Redis发现内存的使用量超过了某一个阀值,将触发swap的操作,Redis根据“swappability = age*log(size_in_memory)”计 算出哪些key对应的value需要swap到磁盘。然后再将这些key对应的value持久化到磁盘中,同时在内存中清除。这种特性使得Redis可以 保持超过其机器本身内存大小的数据。当然,机器本身的内存必须要能够保持所有的key,毕竟这些数据是不会进行swap操作的。同时由于Redis将内存 中的数据swap到磁盘中的时候,提供服务的主线程和进行swap操作的子线程会共享这部分内存,所以如果更新需要swap的数据,Redis将阻塞这个 操作,直到子线程完成swap操作后才可以进行修改。

使用Redis特有内存模型前后的情况对比:

VM off: 300k keys, 4096 bytes values: 1.3G used
VM on:  300k keys, 4096 bytes values: 73M used
VM off: 1 million keys, 256 bytes values: 430.12M used
VM on:  1 million keys, 256 bytes values: 160.09M used
VM on:  1 million keys, values as large as you want, still: 160.09M used

当 从Redis中读取数据的时候,如果读取的key对应的value不在内存中,那么Redis就需要从swap文件中加载相应数据,然后再返回给请求方。 这里就存在一个I/O线程池的问题。在默认的情况下,Redis会出现阻塞,即完成所有的swap文件加载后才会相应。这种策略在客户端的数量较小,进行 批量操作的时候比较合适。但是如果将Redis应用在一个大型的网站应用程序中,这显然是无法满足大并发的情况的。所以Redis运行我们设置I/O线程 池的大小,对需要从swap文件中加载相应数据的读取请求进行并发操作,减少阻塞的时间。

如果希望在海量数据的环境中使用好Redis,我相信理解Redis的内存设计和阻塞的情况是不可缺少的。

docker-php添加redis扩展

环境及版本

  • php: php:5-fpm-alpine
  • docker: version 17.06.1-ce
  • docker-compose: version 1.16.0-rc2

源码安装方式

ENV PHPREDIS_VERSION 3.1.3
RUN curl -L -o /tmp/redis.tar.gz https://github.com/phpredis/phpredis/archive/$PHPREDIS_VERSION.tar.gz 
    && tar xfz /tmp/redis.tar.gz 
    && rm -r /tmp/redis.tar.gz 
    && mkdir -p /usr/src/php/ext 
    && mv phpredis-$PHPREDIS_VERSION /usr/src/php/ext/redis 
    && docker-php-ext-install redis 
    && rm -rf /usr/src/php #如果这段不加构建的镜像将大100M 

PECL安装方式

#添加扩展 redis pecl方式
RUN apk add --no-cache --update libmemcached-libs zlib
RUN set -xe 
    && apk add --no-cache --update --virtual .phpize-deps $PHPIZE_DEPS 
    && pecl install -o -f redis  
    && echo "extension=redis.so" > /usr/local/etc/php/conf.d/redis.ini
    && rm -rf /usr/share/php 
    && rm -rf /tmp/* 
    && apk del  .phpize-deps

Linux CentOS 7安装Redis服务器教程

说明:redis的缩写是REmote DIctionary Server。它是最流行的开源,高级key-value存储系统。这里说下CentOS 7上安装redis服务器方法。

项目地址:http://redis.io/

安装

一、安装EPEL repo

这里用的CentOS x86_64操作系统架构,所以我将仅使用适用于x86_64的epel repo软件包。请根据您的操作系统架构(EPEL URL)搜索epel repo软件包

yum install wget
wget -r --no-parent -A 'epel-release-*.rpm' http://dl.fedoraproject.org/pub/epel/7/x86_64/e/
rpm -Uvh dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-*.rpm

之后将会在/etc/yum.repos.d中创建两个epel的repo文件。分别是epel.repo和epel-testing.repo。

二、安装Redis服务器

1、yum安装redis服务器

yum install redis

两个重要的redis服务器配置文件的路径/etc/redis.conf和/etc/redis-sentinel.conf。

2、启动redis服务器

systemctl start redis.service

3、检查redis服务器的运行状态

systemctl status redis.service

4、测试Redis的安装

redis-cli ping

如果返回结果PONG,则安装成功。

三、redis服务器相关命令

systemctl start redis.service  #启动redis服务器 
systemctl stop redis.service  #停止redis服务器
systemctl restart redis.service  #重新启动redis服务器 
systemctl status redis.service  #获取redis服务器的运行状态 
systemctl enable redis.service  #开机启动redis服务器
systemctl disable redis.service  #开机禁用redis服务器

四、Redis服务器监听端口

Redis Server默认侦听端口号6379,可使用SS命令查看。

ss -nlp|grep redis

学习Redis请看:http://redis.io/documentation