<shell>迭代读取redis解决数据不稳定问题

问题背景: php读取线上redis数据,经常不稳定,数据响应时有时无。

解决方法:多次读取,每次读取所有上一次没读出的数据,直到全部获取。

本文实现用shell进行多次redis数据读取, 每次取出其中的有效值(对于我们的例子中,就是给key,能在redis上取得其value的为有效值,其他无效),并将无效值重跑一遍,以此迭代,直到所有redis数据被取出。PS:redis数据可以由php或C读出,给定接口的话非常简单,具体可以参考phpredis,,由于可能涉密,本文中不给出这块的实现。


  1. 方法概述:

    1. 将source中的key分为N个文件,丢入redis并行get value
    2. 实时统计N个文件get value输出结果的总行数,以及其中有效的行数
    3. N个文件统计结束后, 将其所有结果合并,放入result/step/stepx.res
    4. 删除原先并行的的source文件,结果文件
    5. 将result中未获取到的key放入source/step2/contsigns,作为下一轮的输入,再次将其分为N个文件,运行(这里的contsign就是redis的key)
    6. 最后将各个step所得结果都写入final.res文件。cat result/steps/step*.res >> final.res
  2. 项目结构:

    • getredis.php: 实现获取redis数据
    • all.sh: 主程序,并行执行getredis.php;
    • analyze_result.sh: 实时分析redis获取数据执行情况(第2步), 加参数后实现上面的第3-5步(具体见下一节注释);
    • source/:存储输入数据,其中all/下为原始所有redis的输入, step2/为这一轮中未获取到的key,将作为下一轮获取redis的输入, 其余(如xaa)为当前这一轮中key分成的N个文件;
    • result/: 存储结果,其中source/包含当前一轮source下所有N个文件的输出;steps/包含各轮输出后的合并结果
  3. 具体实现:

    all.sh :

#Author:Rachel Zhang
#Email: [email protected]

for file in source/*
do
    {
        echo "processing source $file"
        if test -f $file
        then
            php getredis.php $file > result/$file
        fi
        echo "$file done..."
    }&
done


analyze_result.sh:

#Author:Rachel Zhang
#Email: [email protected]

Filefolder=result/source/*
#Filefolder=source/*

echo "##################################"
echo "     In Folder $Filefolder"
echo "##################################"
nl=0
hv=0
for file in $Filefolder
do
    if test -f $file
    then
        fline=`wc -l $file | awk ‘{print $1}‘`
        nl=$(($nl+$fline))
        fvalue=`cat $file |awk ‘BEGIN{x=0;}{if($2) x=x+1;}END{print x;}‘`
        hv=$(($hv+$fvalue))
    fi
done

echo "totally $nl lines"
echo "$hv lines have tag value"

##################################
#combine results into one file

if [ "$#" -gt 0 ]
then
    if test -e "result/all.result"
    then
        mv result/all.result result/all.result.bak
    fi

    for file in $Filefolder
    do
        if test -f $file
        then
            cat $file >> result/all.result
        fi
    done
    echo "all the output are write in result/all.result"

    # put null-value keys into source/step2/contsigns
    if  test -e source/step2
    then
        mkdir source/step2
    fi
    cat result/all.result| awk ‘{if($2==null) print}‘ > source/step2/contsigns
    Nnull_value=`wc -l source/step2/contsigns | awk ‘{print $1}‘`
    echo "remaining ${Nnull_value} keys to be processed"

    # put has-value key-value into result/steps/step${step_id}.res
    step_id=1
    while test -e result/steps/step${step_id}.res
    do
        step_id=$(($step_id+1))
    done
    cat result/all.result | awk ‘{if($2) print}‘ > result/steps/step${step_id}.res
    echo "current valid results are writen in result/steps/step${step_id}.res"

    # remove the current source files, generate new source files and re-run all.sh
    echo "remove current source and result files? (y/n)"
    read answer
    if [ $answer == "y" ]; then
        if [ $Nnull_value -gt 10 ]; then
            rm source/*
            rm result/source/*
            cd source && split -l 5000 step2/contsigns && cd ../
            echo "now re-run sh ./all.sh? (y/n)"
            read answer
            if [ $answer == "y" ]; then
                sh all.sh
            fi
        fi
    fi
fi

PS: 以上analyze_result.sh 还可以去掉analyze_result.sh中的interactive部分(无需用户输入),通过crontab进行定时,进一步自动化执行。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-11 05:10:18

<shell>迭代读取redis解决数据不稳定问题的相关文章

logstash无法读取redis数据

今天搭建logsatsh+redis+elasticsearch时出现了问题,经过近一小时排查,终于解决.记录一下. 环境是这样,一台客户端发送数据到位于服务器的redis,服务器端的logstash读redis的数据,存储到elasticsearch中. 初步问题是这样的:在服务器端,没有收到客户端发送过来的日志. 这样就可能有两种问题:一是客户端的logstash没有成功发送数据到redis,二是服务器端的logstash无法从redis读取数据. 排查问题一 为了避免redis中原有数据影

CentOS6.4 安装OpenResty和Redis 并在Nginx中利用lua简单读取Redis数据

1.下载OpenResty和Redis OpenResty下载地址:wget http://openresty.org/download/ngx_openresty-1.4.3.6.tar.gz Redis下载地址:wget http://download.redis.io/releases/redis-2.8.6.tar.gz 2.安装依赖包 yum install -y gcc gcc-c++ readline-devel pcre-devel openssl-devel tcl perl

logstash读取redis数据

类型设置: logstash中的redis插件,指定了三种方式来读取redis队列中的信息. list=>BLPOP                                    (相当于队列) channel=>SUBSCRIBE                     (相当于发布订阅的某个特定的频道) pattern_channel=>PSUBSCRIBE       (相当于发布订阅某组频道) 其中list,相当于队列:channel相当于发布订阅的某个特定的频道:pat

JAVA TcpServer端使用Scanner读取不到数据的解决办法

在使用JAVA进行Socket通信时,在Server端使用Scanner的nextLine()方法读取数据时,一直读取不到数据是因为Scanner是一个扫描器,它扫描数据都是去内存中一块缓冲区中进行扫描并读入数据的,而我们在控制台中输入的数据也都是被先存入缓冲区中等待扫描器的扫描读取.这个扫描器在扫描过程中判断停止的依据就是“空白符”,空格.回车都算做是空白符.nextInt()方法在扫描到空白符的时候会将前面的数据读取走,但会丢下空白符“\r”在缓冲区中,但是,nextLine()方法在扫描的

Python读取redis数据

以读取redis的list数据类型为例 1.首先导入redis类 2.使用redis.Redis连接redis,参数为host和port 3.取特定长度的字段使用lrange函数.lrange(self, name, start, end),结果为python的list类型 如下是个小例子 import redis r=redis.Redis(host='****',port=*****) n=r.lrange('a',start=0,end=1) 可以使用llen函数查看制定key的value

redis之数据操作详解

redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorted set --有序集合)和hash(哈希类型).这些数据类型都支持push/pop.add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的.在此基础上,redis支持各种不同方式的排序.与memcached一样,为了保证效率,数据都是缓存在内存中.区别的是redis会周期性的把更新的数

redis学习——数据持久化

一.概述 Redis的强大性能很大程度上都是因为所有数据都是存储在内存中的,然而当Redis重启后,所有存储在内存中的数据将会丢失,在很多情况下是无法容忍这样的事情的.所以,我们需要将内存中的数据持久化!典型的需要持久化数据的场景如下: 将Redis作为数据库使用: 将Redis作为缓存服务器使用,但是缓存miss后会对性能造成很大影响,所有缓存同时失效时会造成服务雪崩,无法响应. 本文介绍Redis所支持的两种数据持久化方式. 二.Redis数据持久化 Redis支持两种数据持久化方式:RDB

进阶的Redis之数据持久化RDB与AOF

大家都知道,Redis之所以性能好,读写快,是因为Redis是一个内存数据库,它的操作都几乎基于内存.但是内存型数据库有一个很大的弊端,就是当数据库进程崩溃或系统重启的时候,如果内存数据不保存的话,里面的数据就会丢失不见了.这样的数据库并不是一个可靠的数据库. 所以数据的持久化是内存型数据库的重中之重.它不仅提供数据保存硬盘的功能,还可以借此用硬盘容量扩展数据存储空间,使得Redis的可以存储超过机器本身内存大小的数据. Redis对于数据持久化提供了两种持久化的方案,RDB与AOF.它们的原理

如何运用PHP+REDIS解决负载均衡后的session共享问题

一.为什么要使用Session共享? 稍大一些的网站,通常都会有好几个服务器,每个服务器运行着不同功能的模块,使用不同的二级域名,而一个整体性强的网站,用户系统是统一的,即一套用户名.密码在整个网站的各个模块中都是可以登录使用的.各个服务器共享用户数据是比较容易实现的,只需要在后端放个数据库服务器,各个服务器通过统一接口对用户数据进行访问即可.但还存在一个问题,就是用户在这个服务器登录之后,进入另一个服务器的别的模块时,仍然需要重新登录,这就是一次登录,全部通行的问题,映射到技术上,其实就是各个