‘壹’ 在php中 为什么不能使用redis类
redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)和zset(有序集合)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
Redis 是一个高性能的key-value数据库。redis的出现,很大程度补偿了memcached这类keyvalue存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。它提供了Python,Ruby,Erlang,PHP客户端,使用很方便。
若想在PHP中使用redis,首先要先安装redis。然后在PHP中配置扩展。
安装redis。
首先下载好redis安装文件,解压到D盘或其他盘。
然后通过Dos命令行进行安装。
把这个文件夹复制到其它地方,比如D:\redis 目录下。
打开一个cmd窗口 使用cd命令切换目录到D:\redis 运行 redis-server.exe redis.conf
如果想方便的话,可以把redis的路径加到系统的环境变量里,这样就省得再输路径了,后面的那个redis.conf可以省略,如果省略,会启用默认的。
这时候另启一个cmd窗口,原来的不要关闭,不然就无法访问服务端了
切换到redis目录下运行 redis-cli.exe -h 127.0.0.1 -p 6379
这时候,就已经完成配置了。
完成了配置之后,要在PHP中添加redis的扩展,之后才可以用PHP灵活的使用它。
在windows下安装php的redis扩展非常简单,下载一个.dll扩展包放到php的ext目录下,在php.ini里边添加一行配置就可以了。
php代码测试
redis=newRedis();redis->connect(‘127.0.0.1′,6379);
redis−>set(‘test′,′helloworld!′);echoredis->get(‘test’);
输出hello world!
‘贰’ php 怎么把session写入redis
一、 安装phpredis扩展
php连接redis需要安装phpredis扩展。
下载地址:https://github.com/phpredis/phpredis/releases,选用相应版本。
笔者用的是php5.6.29,下载了phpredis-3.0.0安装出了问题,于是换成phpredis-2.2.8,正常。
# tar zxvf phpredis-2.2.8.tar.gz && cd phpredis-2.2.8
# /usr/local/php/bin/phpize
# ./configure --with-php-config=/usr/local/php/bin/php-config
# make && make install
正常情况下会提示在下面目录下生成redis.so文件
Installing shared extensions: /usr/local/php/lib/php/extensions/no-debug-non-zts-20131226/
# sed -i '$aextension="redis.so"' /usr/local/php/etc/php.ini
# service httpd restart
验证:
# php -i | grep redis | grep -xq redis && echo ok || echo "phpredis extended failure"
二、 配置php连接redis(笔者使用的阿里云redis)
# sed -i 's/session.save_handler.*/session.save_handler = redis/' /usr/local/php/etc/php.ini
# sed -i '/session.save_handler/asession.save_path ="tcp://xxxx.rds.aliyuncs.com?auth=redis密码"' /usr/local/php/etc/php.ini
# service httpd restart
‘叁’ java subscribe监听超时怎么解决
问题描述
redis提供了pub/sub功能,但在使用phpredis的subscribe时发现这样一个问题,代码如下(sub.php):
<?php/*监听demo频道,打印收到的信息*/function process($redis, $chan, $msg){
var_mp($msg);
}$redis = new Redis();$res = $redis->connect('127.0.0.1', '7979');$redis->subscribe(array('demo'), 'process');123456789
代码运行后,发现如果在一段时间内未收到来自demo频道的消息,则会报如下错误:
PHP Fatal error: Uncaught exception 'RedisException' with message 'read error on connection' in sub.php:11Stack trace:#0 /search/ballqiu/sub.php(11): Redis->subscribe(Array, 'process')#1 {main}
thrown in sub.php on line 1112345
原因分析
为了查找原因,我们使用strace对代码进行了跟踪:
strace php sub.php1
截取部分重要输出如下:
//连接redis
connect(3, {sa_family=AF_INET, sin_port=htons(7979), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress)
//发送subscribe命令
sendto(3, "subscribe demo
", 17, MSG_DONTWAIT, NULL, 0) = 17//收到响应
recvfrom(3, "*3
$9
subscribe
$4
demo
:1
"..., 8192, MSG_DONTWAIT, NULL, NULL) = 33poll([{fd=3, events=POLLIN|POLLPRI|POLLERR|POLLHUP}], 1, 0) = 0 (Timeout)
//套机字超时时间设为60s
poll([{fd=3, events=POLLIN|POLLERR|POLLHUP}], 1, 60000) = 0 (Timeout)
//等待超时,关闭连接
close(3) = 0//输出错误信息
write(2, "PHP Fatal error: Uncaught excep"..., 261PHP Fatal error: Uncaught exception 'RedisException' with message 'read error on connection' 12345678910111213
可见报错的本质是poll设置接收超时所致,从starce结果我们知道这个超时默认是60s。
解决
我们有两种方法改变超时
- 方法1
在代码起始处设置
ini_set('default_socket_timeout', -1);1
方法2
在redis connect后执行
两种方法中的-1均表示永不超时,你也可以将超时设置为自己希望的时间。
无论使用哪种方法,再次strace, 你会发现poll的超时被设为了-1。
个人比较推荐方法2,它只影响到redis本身。而方法1会对其它方法产生影响,比如
file_get_contents等。
总结
使用phpredis的subscribe时,默认60内没有收到消息,sub端就会因超时异常退出。可以自行设置延长超时时间或永不超时。
‘肆’ 用PHP+Redis实现延迟任务 实现自动取消订单(详细教程)
使用PHP和Redis实现延迟任务,如自动取消订单,可以借助Redis 2.8版本及以上提供的keyspace notifications功能。这个特性会在指定键失效时发送通知,适合处理如业务触发后需定时执行的任务场景。
首先,你需要在Redis配置中开启keyspace notifications,虽然这会增加CPU消耗,但为了实时监控,这是必要的。Windows用户需修改`redis.windows.conf`,将默认配置中的keyevent和过期事件(x)启用。重启服务后,配置生效。
接下来,用PHPredis扩展编写监听脚本。例如,你可以创建`db.class.php`、`index.php`、`psubscribe.php`和`Redis2.class.php`文件来处理过期事件。在`psubscribe.php`中,使用nohup命令确保脚本后台运行,即使终端关闭也能继续监听。遇到MySQL连接问题,可通过调整`wait_timeout`参数或在业务逻辑完成后主动断开连接解决。
最后,使用`jobs -l`查看和管理后台进程,确保nohup.out文件的清理以及正确退出当前账户,以保持命令的持续运行。完整教程中还提到,作者提供了更多进阶学习资源,如分布式架构、性能优化等内容,供需要的开发者参考。
‘伍’ thinkphp redis 怎么选择数据库
1、redis 中的每一个数据库,都由一个 redisDb 的结构存储。其中,redisDb.id 存储着 redis 数据库以整数表示的号码。redisDb.dict 存储着该库所有的键值对数据。redisDb.expires 保存着每一个键的过期时间。
2、当redis 服务器初始化时,会预先分配 16 个数据库(该数量可以通过配置文件配置),所有数据库保存到结构 redisServer 的一个成员 redisServer.db 数组中。当我们选择数据库 select number 时,程序直接通过 redisServer.db[number] 来切换数据库。有时候当程序需要知道自己是在哪个数据库时,直接读取 redisDb.id 即可。
3、既然我们知道一个数据库的所有键值都存储在redisDb.dict中,那么我们要知道如果找到key的位置,就有必要了解一下dict 的结构了:
typedef struct dict {
// 特定于类型的处理函数
dictType *type;
// 类型处理函数的私有数据
void *privdata;
// 哈希表(2个)
dictht ht[2];
// 记录 rehash 进度的标志,值为-1 表示 rehash 未进行
int rehashidx;
// 当前正在运作的安全迭代器数量
int iterators;
} dict;
由上述的结构可以看出,redis 的字典使用哈希表作为其底层实现。dict 类型使用的两个指向哈希表的指针,其中 0 号哈希表(ht[0])主要用于存储数据库的所有键值,而1号哈希表主要用于程序对 0 号哈希表进行 rehash 时使用,rehash 一般是在添加新值时会触发,这里不做过多的赘述。所以redis 中查找一个key,其实就是对进行该dict 结构中的 ht[0] 进行查找操作。
4、既然是哈希,那么我们知道就会有哈希碰撞,那么当多个键哈希之后为同一个值怎么办呢?redis采取链表的方式来存储多个哈希碰撞的键。也就是说,当根据key的哈希值找到该列表后,如果列表的长度大于1,那么我们需要遍历该链表来找到我们所查找的key。当然,一般情况下链表长度都为是1,所以时间复杂度可看作o(1)。
二、当redis 拿到一个key 时,如果找到该key的位置。
了解了上述知识之后,我们就可以来分析redis如果在内存找到一个key了。
1、当拿到一个key后, redis 先判断当前库的0号哈希表是否为空,即:if (dict->ht[0].size == 0)。如果为true直接返回NULL。
2、判断该0号哈希表是否需要rehash,因为如果在进行rehash,那么两个表中者有可能存储该key。如果正在进行rehash,将调用一次_dictRehashStep方法,_dictRehashStep 用于对数据库字典、以及哈希键的字典进行被动 rehash,这里不作赘述。
3、计算哈希表,根据当前字典与key进行哈希值的计算。
4、根据哈希值与当前字典计算哈希表的索引值。
5、根据索引值在哈希表中取出链表,遍历该链表找到key的位置。一般情况,该链表长度为1。
6、当 ht[0] 查找完了之后,再进行了次rehash判断,如果未在rehashing,则直接结束,否则对ht[1]重复345步骤。
到此我们就找到了key在内存中的位置了。
‘陆’ 怎么安装redis PHP扩展,windows下
1、首先到相应网站下载redis:
下载完成后解压到任意盘符如:D:/redis
里面包括:如图所示。
redis-server.exe:服务程序
redis-check-mp.exe:本地数据库检查
redis-check-aof.exe:更新日志检查
redis-benchmark.exe:性能测试,用以模拟同时由N个客户端发送M个 SETs/GETs 查询 (类似于 Apache 的ab 工具).
当然还需要一个:redis.conf(具体内容网上随便搜都会有)
8、PHP代码测试
$redis = new Redis();
$redis->connect("192.168.138.2","6379"); //php客户端设置的ip及端口
//存储一个 值
$redis->set("say","Hello World");
echo $redis->get("say"); //应输出Hello World
//存储多个值
$array = array('first_key'=>'first_val',
'second_key'=>'second_val',
'third_key'=>'third_val');
$array_get = array('first_key','second_key','third_key');
$redis->mset($array);
var_mp($redis->mget($array_get));