存档

‘Redis’ 分类的存档

如何将redis一个list中的数据全部移动到另一个list

2018年7月21日 没有评论

有时候我们需要将一个list中的数据全部移动到另一个list中,而Redis目前没有直接提供这样的命令。

怎么办?

很简单,逐一pop出list a中的数据,再push到list b中。当然pop+push可以通过rpoplpush来实现。所以对源list做个遍历就行了。

#!/bin/sh

host=”127.0.0.1″
port=”6379″
passwd=”foobar”
srcList=”listSrc”
dstList=”listDest”

while[ 1 == 1 ];do
ret=$(redis-cli -h $host -p $port -a $passwd rpoplpush $srcList $dstList)
[ -z $ret ] && return
done

分类: Redis 标签:

非root用户启动和运行redis

2018年5月30日 没有评论

    redis之前爆出过一个漏洞,攻击者可藉此漏洞获取系统root权限。在之前的文章里,我们了解了如何增强redis的安全性。我们还可以使用非root用户来运行redis,进而进一步提升系统安全性。

  1. 以root身份正常安装redis
  2. 切换非root用户登入系统,比如test
  3. 拷贝redis默认配置文件到test的根目录(或其他test有访问权限的目录):

    sudo copy /etc/redis/6379.conf /home/test/

  4. 修改test下配置文件的属主:

    sudo chown test.test /home/test/6379.conf

  5. 修改配置文件中redis运行使用到的相关文件和目录的路径,可通过grep 6379 /home/test/6379.conf查找这些文件和目录,将这些路径修改到test用户根目录下

    pidfile /home/test/run/redis_6379.pid
    logfile /home/test/log/redis_6379.log
    dir /home/test/lib/redis/6379

  6. 创建这些文件和目录

    mkdir -p /home/test/run/ /home/test/log  /home/test/lib/redis/6379

  7. 启动redis

    /usr/local/bin/redis-server /home/test/6379.conf

分类: Redis, 安全, 开发 标签:

使用openresty+redis轻松实现网站访问统计

2017年2月16日 没有评论

网站的受访统计是网站运营和优化的一个重要参考数据,对于并发量较大的网站,我们可以通过nginx+redis的架构来简单实现页面受访统计。这主要得益于nginx的高并发性能和redis快速存取内存数据。实际应用中,我们可以使用openresty来快速搭建统计系统。

openresty集合了lua和lua-redis访问库,可以通过编写nginx.conf配置文件实现对redis数据库的存取。简单且高效。

  1. 安装和配置openresty及redis
  2. 修改nginx.conf,示例:

    http {
    include mime.types;
    default_type application/octet-stream;
    sendfile on;
    keepalive_timeout 65;

    server {
    listen 8088;
    server_name www.test.com;

    location /get_pv {
    set $id_param $args;
    content_by_lua ‘
    local redis_mod = require “resty.redis”
    local redis_db= redis_mod:new()
    redis_db:set_timeout(1000) — 1 second

    local ok, err = redis_db:connect(“127.0.0.1″, 6379)
    if not ok then
    ngx.log(ngx.ERR, “failed to connect to redis: “, err)
    return ngx.exit(500)
    end

    local id = string.sub(ngx.var.id_param, 4)
    local pv, err = redis_db:get(id)
    if not pv then
    redis_db:close()
    ngx.log(ngx.ERR, “failed to get redis key: “, id, err)
    return ngx.exit(500)
    end

    if pv == ngx.null then
    redis_db:close()
    ngx.log(ngx.ERR, “no pv found for “, id)
    return ngx.exit(400)
    end

    redis_db:close()

    ngx.header.content_type = “text/plain”;
    ngx.say(pv)
    ‘;
    }
    }

    server {
    listen 9099;
    server_name www.test.com;

    location /set_pv {
    set $id_param $args;
    content_by_lua ‘
    local redis_mod = require “resty.redis”
    local redis_db= redis_mod:new()
    redis_db:set_timeout(1000) — 1 second

    local ok, err = redis_db:connect(“127.0.0.1″, 6379)
    if not ok then
    ngx.log(ngx.ERR, “failed to connect to redis: “, err)
    return ngx.exit(500)
    end

    local id = string.sub(ngx.var.id_param, 4)
    local pv = redis_db:incr(id)
    if not pv then
    redis_db:close()
    ngx.log(ngx.ERR, “failed to incr redis key: “, id, err)
    return ngx.exit(500)
    end

    redis_db:close()

    ngx.header.content_type = “text/plain”;
    ngx.say(pv)
    ‘;
    }
    }
    }

  3. 在网站页面中部署统计代码

<iframe frameborder=”0″ scrolling=”no” width=”0″  height=”0″ style=”display:none;” src=”http://www.test.com:9099/set_pv?id=page_411“></iframe>

分类: Lua, Redis, 开发 标签: , , ,

Redis低版本无法向前兼容高版本RDB文件

2016年9月26日 没有评论

今天做了一个操作导致Redis无法启动。

在部署某一程序的过程中,先是单独安装了3.2.3版本的redis,安装完成后ps一下,redis已经启动。然后又使用安装包部署程序,安装包中包含一个2.8.13版本的redis,直接把之前装的3.2.3的redis给覆盖掉了。程序安装完成后发现redis进程没了,而且通过service redis_6379 restart无法启动。

怎么回事?查看/var/log/redis_6379.log发现如下错误:

[31934] 26 Sep 11:31:47.087 # Can’t handle RDB format version 7
[31934] 26 Sep 11:31:47.087 # Fatal error loading the DB: Invalid argument. Exiting.

哦,当前版本的redis无法处理version=7的RDB格式,这才明白是兼容性问题,但这种“向前兼容”一般很难做到的。

解决办法:删除rdb文件/var/lib/redis/6379/dump.rdb,重启redis就行了。

2017.11.08:今天在redis官网上看到一篇文章,是介绍redis rdb文件版本历史的,参这里。详细介绍了各版本的演进历史,并说明了高版本rdb文件回退到低版本的方法,有需要的朋友可以了解一下。

分类: Redis, 运维 标签: ,

redis数据类型及应用场景介绍

2016年1月25日 没有评论
  1. string
    • 这是Redis最基本的数据类型。string是二进制安全的,意味着可以存储各种类型的数据,比如一张JEPG图片或者一个序列化过的Ruby对象。
    • 最普通的KV缓存操作:set str_key str_value, get str_key
    • 原子计数器:incr str_key, decr str_key, incrby str_key 1
    • 获取子串:getrange str_key 0 3
  2. list
    • 双端有序队列,可方便地在头部和尾部插入或删除数据
    • 消息队列:rpush list_key member, lpop/blpop list_key. 可用于线程、进程间通信。
    • 可信消息队列:list用作消息队列,消息获取者取数据过程中若发生异常(崩溃、网络断开等),会导致数据已pop出队列而获取者并未得到数据。因此有必要将取出的消息先放在一个“正在处理”队列中,获取中处理完成后再从“正在处理”队列中将消息删除。rpoplpush msgQueue msgProcessingQueue一个命令即可完成出队和入队操作,消息处理完毕使用lrem msgProcessingQueue 0 msg将消息彻底删除。
    • 时间轴(Timeline):通过lpush不断地将事件插入队列,通过lrange取出最近发生的几个事件。
    • 循环(Circular)队列:将N个数据lpush入队列CircularList,然后通过rpoplpush CircularList CircularList即可循环访问此队列中的数据。
    • 定长最新队列:将数据lpush进队列,并通过ltrim 0 MaxLen-1保留指定索引范围内的元素,可以使得队列长度不超过设定的值MaxLen,此时队列中始终保存这最新的MaxLen个数据。
  3. set
    • 无序不重复的string集合,向其中添加、删除、查找元素的时间效率均为常量级O(1)。
    • 数据去重:sadd set_key member
    • 集合交并补运算:sinter skey1 …, sunion skey1 …, sdiff skey1 …
  4. zset
    • 带有分值(score)的set,有了分值就可以对set进行排序。zset同样是key不重复,但是和key关联的score却可以相同。
    • 计数:zadd sset_key score member, zincrby sset_key increment member, zscore sset_key member
    • Top N:zrange/zrevrange sset_key 0 N-1 [withscores]
    • 范围查询:zrangebyscore sset_key min_score max_score [withscores] [limit offset count]
    • 排名查询:zrank sset_key member
  5. hash
    • string键值对映射,其实称作键-域-值三元组更合适,因为每个hash key中可以存储多个不同的域,每个域里存储对应的数据。这就适合用来存储对象,对象包含多个属性,各属性都有自己的值。
    • 映射合集:hset hkey field1 value1, hget hkey filed1, hmset hkey2 field1 value2 field2 valuex
    • 计数:hincrby hkey filed increment
分类: Redis 标签:

安装redis需要注意的几点信息

2016年1月25日 没有评论
  • 建议将redis部署在linux系统上。除了各平台上反复的测试外,官方在linux上做了所有的重要的压力测试,并且linux也是应用最多的生产环境。
  • 将linux内核参数overcommit memory设置为1.添加vm.overcommit_memory = 1到/etc/sysctl.conf,重启系统,或者执行sysctl vm.overcommit_memory=1使该配置立即生效。
  • 禁用内核transparent huge pages特性,因为该参数会给redis的内存使用和延迟处理带来负面影响。禁用方法:echo never > /sys/kernel/mm/transparent_hugepage/enabled.
  • 系统要创建swap分区,建议分区大小和物理内存大小保持一致。redis可能偶尔会消耗太多内存,如果没有swap交换分区,redis很有可能会由于内存耗尽而崩溃,或者被内核OOM killer杀掉。
  • 通过设置redis.conf中的maxmemory参数明确的限制redis可占用的内存空间。这样当redis使用的内存达到限定值时会给出报错信息,而不是失败退出。
  • 如果redis应用在一个写频繁的环境中,redis执行存盘操作(rdb或aof)时,有可能会占用正常状态下2倍的内存空间,额外占用的内存空间和存盘时被改动的key的数量相关。这种场景下需要合理的调整内存配置。
  • redis本身可工作在守护模式下,如果使用其他的工具来守护redis,请将redis.conf中的daemonize设置为no。
  • 即便你禁用了持久化配置(如save “”),redis在执行复制操作时仍会保存rdb快照,除非使用试验中的diskless复制特性。意思是,如果不使用diskless复制,你仍需关注redis的内存配置和系统磁盘使用情况。
  • 使用复制功能时,要么主redis开启了持久化功能,要么主redis不可以在崩溃后自动重启。否则,如果主redis关闭了持久化功能,并且崩溃时自动重启了,重启后的主redis已不含数据,它还会将备redis的数据清空。这样所有的数据都没了。
  • 默认情况下,redis监听所有的网卡,且没有任何认证机制,这会带来一定的安全隐患,需要根据实际情况正确配置redis的安全参数
分类: Redis, 运维 标签:

一种向redis中插入大批量数据的方法

2016年1月7日 没有评论
  • 场景描述

向redis中插入单条数据是件很简单的事:set kye1 value1 就ok了,但是如果需要将成千上万条数据导入redis,又该怎么做?显然不能一条命令一条命令的执行,效率很低。

  • 解决方法

通常我们会想到使用redis自身支持的pipeline机制,一次性发送多条插入命令到服务器。然而这并不是官方推荐的做法,因为需要手工检查服务器的响应,同时还需要新的策略来确保插入速度尽可能得快。

官方给出了一个优选的方法:将数据以redis裸(raw)协议的方式存储在文本文档data.txt中,并调用用以插入数据的命令。举个栗子。

如果要生成一个包含数十亿“keyN -> ValueN”格式数据的大数据集,需要创建一个包含如下命令的redis裸协议格式的文件:

  SET Key0 Value0

  SET Key1 Value1 …

  SET KeyN ValueN

然后将这个redis裸协议文件尽可能快的导入redis。可通过以下命令进行导入:

(cat data.txt; sleep 10) | nc localhost 6379 > /dev/null

但上面这个命令对于大批量导入并不可信,因为netcat无法获知是否所有数据都发送到服务器,也不清楚这个过程中是否发生了什么错误。

redis2.6及后续版本的客户端程序redis-cli为我们提供了一种新的模式:pipe mode。这种模式就是为了应对大批量数据插入这种场景的。于是上面的导入命令变成:

cat data.txt | redis-cli --pipe

执行效果如下:

  All data transferred. Waiting for the last reply...
  Last reply received from server.
  errors: 0, replies: 1000000

如果有错误发生,redis-cli也会输出在屏幕上。

  • 运行机制

redis-cli –pipe会尽可能快的向服务器发送数据,同时它从输入端读取数据并尽力进行解析。一旦输入端没有更多的数据,redis-cli将向服务器发送一个echo命令,附带一个随机的20字节字符串。redis-cli会保证这个echo命令是被最后发出的,并且相信会匹配到服务器响应的一致的字符串。一旦它发出了这个echo命令,响应处理代码就会开始从服务器的reply中匹配这个20字节的字符串。

通过这种方式,redis-cli不必解析要发送的数据,它只需解析响应数据便可知道有多少条数据被成功地导入到了服务器中。

本文参考redis官方文档,如需查看原文,请移步redis-mass-insertion.

 
分类: Redis 标签: ,

Redis视频教程之事务和持久化

2015年12月24日 没有评论
分类: Redis, 资料 标签: , ,

Redis视频教程之常用命令

2015年12月24日 没有评论
分类: Redis, 资料 标签: , ,

Redis视频教程之set和zset数据结构

2015年12月24日 没有评论
分类: Redis, 资料 标签: , ,