redis使用小結

jopen 9年前


NoSQL介绍


NoSQL是以key-value形式存储,特点:非关系型的,分布式的,开源的,水平可扩展的


1.处理超大量的数据
2.运行在便宜的PC服务器集群上
3.击碎了性能瓶颈


NoSQL适用场景
1.对数据高并发读写
2.对海量数据的高效率存储和访问
3.对数据的高可扩展性和高可用性


Redis的介绍
开源的,key-value存储,通常被称为数据结构服务器 
键可以包含字符串strings,哈希hashes,链表lists,集合sets,有序集合sorted sets
这些数据类型都支持 push/pop,add/remove及取交集和并集以及更丰富的操作
Redis支持不同方式的排序
数据都缓存在内存中,也可以周期性的把更新的数据写入磁盘,或者把修改操作写入追加的记录文件


Redis适用场合


新浪微博redis的部署场景很多,大概分2种:
1.应用程序直接访问Redis数据库
2.应用程序直接访问Redis,只有当Redis访问失败的时候才访问MySQL


应用场景:
1.取最新的N个数据的操作
2.排行榜应用,取TOP N的操作
3.需要精确设定过期时间的应用
4.计数器应用
5.Uniq操作,获取某段时间所有数据排重值 唯一操作
6.实时系统,反垃圾系统
7.pub/sub构建实时消息系统
8.构建队列系统
9.缓存


redis             MySQL            mongodb 区别
1.库              库               库


2.无表            有表             集合-类似于MySQL的表


3.无字段、行、列  有字段、行、列   无字段、行、列




redis的安装
官网:http://redis.io/download
稳定版 2.4.17


1.下载安装包
wget http://redis.googlecode.com/files/redis-2.4.17.tar.gz


2.编译源程序
tar -zxvf redis-2.4.17.tar.gz
cd redis-2.4.17
make
cd src && make test


make test 的时候如果出现
You need tcl 8.5 or newer in order to run the Redis test
make: ** [test] Error 1
这样的错误,则需要安装tcl
下载tcl
wget http://downloads.sourceforge.net/tcl/tcl8.6.0-src.tar.gz cd tcl8.6.0/ cd unix && ./configure --prefix=/usr \
            --mandir=/usr/share/man \ --without-tzdata \
            $([ $(uname -m) = x86_64 ] && echo --enable-64bit) && make && sed -e "s@^(TCL_SRC_DIR=').
@\1/usr/include'@" \ -e "/TCL_B/s@='(-L)\?.unix@='\1/usr/lib@" \ -i tclConfig.sh


make install && make install-private-headers && ln -v -sf tclsh8.6 /usr/bin/tclsh && chmod -v 755 /usr/lib/libtcl8.6.so
如果是32位机,则需要把x86_64改成x86_32,--enable-64bit 改成32bit


make install


redis没有配置configure 直接进行编译安装


3.移动文件,便于管理
mkdir -p /usr/local/redis/bin
mkdir -p /usr/local/redis/etc
mv /lamp/redis-2.4.17/redis.conf /usr/local/redis/etc
cd /lamp/redis-2.4.17/src
mv mkreleasehdr.sh redis-benchmark redis-check-aof redis-check-dump redis-cli redis-server /usr/local/redis/bin


4.启动redis服务
/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf 指定配置文件
redis服务端的默认连接端口是6379


5.客户端连接
/usr/local/redis/bin/redis-cli


6.停止redis实例
我们可以使用/usr/local/redis/bin/redis-cli shutdown
也可以使用 pkill redis-server


Redis的配置
daemonize 如果需要在后台运行,把该项改为yes
pidfile 配置多个pid的地址 默认为 /var/run/redis.pid
bind 绑定ip 设置后只接受来自该ip的请求
port 监听端口 默认为6379
timeout 设置客户端连接时的超时时间 单位为秒
loglevel 分为4级 debug,verbose,notice,warning
logfile 配置log文件地址
database 设置数据库的个数,默认使用的数据库为0
save 设置redis进行数据库镜像的频率
rdbcompression 在进行镜像备份时,是否进行压缩
Dbfilename 镜像备份文件的文件名
Dir 数据库镜像备份的文件放置路径
Slaveof 设置数据库为其他数据库的从数据库
Masterauth 主数据库连接需要的密码验证
Requirepass 设置登录时需要使用的密码
Maxclients 限制同时连接的客户数量
Maxmemory 设置redis能够使用的最大内存
Appendonly 开启 append only 模式
Appendfsync 设置对appendonly.aof文件同步的频率
vm-enabled 是否开启虚拟内存支持
vm-swap-file 设置虚拟内存的交换文件路径
vm-max-memory 设置redis使用的最大物理内存大小
vm-page-size 设置虚拟内存的页大小
vm-pages 设置交换文件的总的page数量
vm-max-threads 设置VMIO同时使用的线程数量
Glueoutputbuf 把小的输出缓存放在一起
hash-max-zipmap-entries 设置hash的临界值
Activerehashing 重新hash




Redis的数据类型
strings类型及操作
string是最简单的类型,一个key对应一个value,string类型是二进制安全的
redis的string可以包含任何数据,比如JPG图片或序列化的对象


Set
设置key对应的值为string类型的value
例如:添加一个name=lijie的键值对
redis 127.0.0.1:6379> set name lijie
ok


获取设置的name值
redis 127.0.0.1:6379> get name


Setnx
设置key 对应的值为string类型的value
如果key已经存在,返回0,nx是not exists的意思


Setex
设置key 对应的值为string类型的value 并指定此键值对应的有效期
例如:添加一个haircolor=red的键值对,并指定有效期为10秒
redis 127.0.0.1:6379> setex haircolor 10 red


Setrange
设置指定key的value值的子字符串
例如:将lijie的126邮箱替换为gmail邮箱
如果替换的字符串没有原来的字符串长,则长于替换的字符串的字符将被保留
redis 127.0.0.1:6379> get name
"lijie@126.com"


redis 127.0.0.1:6379> setrange name 6 gmail.com
(integer) 15


redis 127.0.0.1:6379> get name
"lijie@gmail.com"


mset
一次设置多个key的值,成功返回OK表示所有的值都设置了,失败返回0表示没有任何值被设置
redis 127.0.0.1:6379> mset key1 lijie1 key2 lijie2
ok
redis 127.0.0.1:6379> get key1
"lijie1"
redis 127.0.0.1:6379> get key2
"lijie2"


msetnx
一次设置多个key的值,成功返回OK表示所有的值都设置了
失败返回0表示没有任何值被设置,但是不会覆盖已经存在的key
如果有键值存在则所有值都不会被设置,返回0


get
获取key对应的string值,如果key不存在则返回nil


getset
设置key的值,并返回key的旧值


getrange
获取key的value值的子字符串
redis 127.0.0.1:6379> getrange name 0 5
0表示起始位置 5表示结束字符位置 就是截取0-5 的字符


mget
一次获取多个key的值,如果对应key不存在,则对应返回nil


incr
对key的值做++操作,并返回新的值


incrby
同incr类似,加指定值,key不存在的时候会设置key,并认为原来的value是0
redis 127.0.0.1:6379> incrby key4 3 key4+3
redis 127.0.0.1:6379> incrby key4 -2 key4-2


decr
对key的值做--操作


decrby
同decr类似,减指定值


append
给指定key的字符串追加value,返回新字符串值的长度
redis 127.0.0.1:6379> append name @lijie.me


strlen
取指定key的value值的长度


del
删除指定key的值
redis 127.0.0.1:6379> del name
(integer) 1


hashes类型


hashes类型及操作
Redis hash 是一个string类型的field和value的映射表
它的添加,删除操作都是0(1)(平均)
hash特别适合用于存储对象
相较于将对象的每个字段存成单个string类型,
将一个对象存储在hash类型中会占用更少的内存 并且可以更方便的存取整个对象


hashes类型


hset
设置hash field 为指定值,如果key不存在,则先创建
redis 127.0.0.1:6379> hset myhash field1 hello


hsetnx
设置hash field 为指定值,如果key不存在,则先创建,如果存在则返回0


hmset
同时设置hash的多个field


hget
获取指定的hash field
hget myhash field1


hmget
获取全部指定的hash field


hincrby
指定的hash field 加上给定的值


hexists
测试指定field是否存在


hlen
返回指定hash的field数量


hdel
删除指定hash的field
redis 127.0.0.1:6379> hdel myhash age


hkeys
返回hash的所有field
redis 127.0.0.1:6379> hkeys myhash


hvals
返回hash的所有value


hgetall
获取某个hash中全部的field以及value
redis 127.0.0.1:6379> hgetall myhash


lists类型


lists类型及操作
list是一个链表结构,主要功能是push,pop,获取一个范围的所有值等等
操作中key理解为链表的名字
redis的list类型起始就是一个每个子元素都是string类型的双向链表
可以通过push,pop操作从链表的头部或者尾部添加删除元素
这样list既可以做栈,又可以作为队列


lists类型
lrange
获取给定key范围的list元素
redis 127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "world"


lpush
在key对应list的头部添加字符串元素
redis 127.0.0.1:6379> lpush mylist "word"
(integer) 1
redis 127.0.0.1:6379> lpush mylist "hello"
(integer) 2
redis 127.0.0.1:6379> lrange mylist 0 -1 // lrange 0表示从头部取,-1表示到尾部
1) "hello"
2) "world"


rpush
在key对应list的尾部添加字符串元素
redis 127.0.0.1:6379> rpush mylist2 "world"
(integer) 1
redis 127.0.0.1:6379> rpush mylist2 "hello"
(integer) 2
redis 127.0.0.1:6379> lrange mylist2 0 -1
1) "world"
2) "hello"


linsert
在key对应list的特定位置前或后添加字符串
redis 127.0.0.1:6379> rpush mylist3 "world"
(integer) 1
redis 127.0.0.1:6379> linsert mylist3 before "world" "hello"
(integer) 2
redis 127.0.0.1:6379>lrange mylist3 0 -1
1) "hello"
2) "world"


Lset
设置list中指定下标的元素值
redis 127.0.0.1:6379> rpush mylist4 "hello"
(integer) 1
redis 127.0.0.1:6379> lset mylist4 0 "world"
ok
redis 127.0.0.1:6379> lrange mylist4 0 -1
1) "world"


lrem
从key对应list中删除n个和value相同的元素 n<0 从尾删除 n=0 全部删除
redis 127.0.0.1:6379> rpush mylist5 "hello"
(integer) 1
redis 127.0.0.1:6379> rpush mylist5 "hello"
(integer) 2
redis 127.0.0.1:6379> lrem mylist5 1 "hello"
(integer) 1


ltrim
保留指定key的值范围内的数据
redis 127.0.0.1:6379> rpush mylist8 "one"
(integer) 1
redis 127.0.0.1:6379> rpush mylist8 "two"
(integer) 2
redis 127.0.0.1:6379> ltrim mylist8 1 -1
(integer) 1
redis 127.0.0.1:6379> lrange mylist8 0 -1
1) "two"


lpop
从list的头部删除元素,并返回删除元素
redis 127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "world"
redis 127.0.0.1:6379> lpop mylist
"hello"
redis 127.0.0.1:6379> lrange mylist 0 -1
1) "world"


rpop
从list的尾部删除元素,并返回删除元素
redis 127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "world"
redis 127.0.0.1:6379> rpop mylist
"world"
redis 127.0.0.1:6379> lrange mylist 0 -1
1) "hello"


rpoplpush
从第一个list的尾部移除元素并添加到第二个list的头部


redis 127.0.0.1:6379> lrange mylist5 0 -1
1) "three"
2) "hello"
redis 127.0.0.1:6379> lrange mylist6 0 -1
1) "hello"
2) "foo"
redis 127.0.0.1:6379> rpoplpush mylist5 mylist6
"hello"
redis 127.0.0.1:6379> lrange mylist5 0 -1
1) "three"
redis 127.0.0.1:6379> lrange mylist6 0 -1
1) "hello"
2) "hello"
3) "foo"


lindex
返回名称为key的list中index位置的元素
redis 127.0.0.1:6379> lrange mylist5 0 -1
1) "three"
2) "foo"
redis 127.0.0.1:6379> lindex mylist5 0
"three"
redis 127.0.0.1:6379> lindex mylist5 1
"foo"


llen
返回key对应list的长度
redis 127.0.0.1:6379> llen mylist5
(integer) 2


Sets类型
sets类型及操作
set是集合,它是string类型的无序集合
set是通过hash table实现的,
添加、删除和查找的复杂度都是0(1)
对集合我们可以取交集、并集、差集
通过这些操作我们可以实现SNS中的好友推荐和blog的tag功能


sadd
向名称为key的set中添加元素
redis 127.0.0.1:6379> sadd myset "hello"
(integer) 1
redis 127.0.0.1:6379> sadd myset "world"
(integer) 1
redis 127.0.0.1:6379> sadd myset "world"
(integer) 0
redis 127.0.0.1:6379> smembers myset
1) "world"
2) "hello"


smembers
获取名称为key的set中所有元素
redis 127.0.0.1:6379> smembers myset
1) "hello"
1) "world"


srem
删除名称为key的set中的元素
redis 127.0.0.1:6379> sadd myset2 "one"
(integer) 1
redis 127.0.0.1:6379> sadd myset2 "two"
(integer) 1
redis 127.0.0.1:6379> srem myset2 "one"
(integer) 1


spop
随机返回并删除名称为key的set中一个元素
redis 127.0.0.1:6379> sadd myset3 "one"
(integer) 1
redis 127.0.0.1:6379> sadd myset3 "two"
(integer) 1
redis 127.0.0.1:6379> spop myset3
"two"


sdiff
返回所有给定key与第一个key的差集
redis 127.0.0.1:6379> smembers myset2
1) "three"
2) "two"
redis 127.0.0.1:6379> smembers myset3
1) "two"
2) "one"
redis 127.0.0.1:6379> sdiff myset2 myset3
1) "three"


sdiffstore
返回所有给定key与第一个key的差集,并将结果存为另一个key
redis 127.0.0.1:6379> smembers myset2
1) "three"
2) "two"
redis 127.0.0.1:6379> smembers myset3
1) "two"
2) "one"
redis 127.0.0.1:6379> sdiffstore myset4 myset2 myset3
(integer) 1
redis 127.0.0.1:6379> smembers myset4
1) "three"


sinter
返回所有给定key的交集
redis 127.0.0.1:6379> smembers myset2
1) "three"
2) "two"
redis 127.0.0.1:6379> smembers myset3
1) "two"
2) "one"
redis 127.0.0.1:6379> sinter myset2 myset3
1) "two"


sinterstore
返回所有给定key的交集,并将结果存为另一个key
redis 127.0.0.1:6379> smembers myset2
1) "three"
2) "two"
redis 127.0.0.1:6379> smembers myset3
1) "two"
2) "one"
redis 127.0.0.1:6379> sinterstore myset4 myset2 myset3
(integer) 1
redis 127.0.0.1:6379> smembers myset4
1) "two"


sunion
返回所有给定key的并集
redis 127.0.0.1:6379> smembers myset2
1) "three"
2) "two"
redis 127.0.0.1:6379> smembers myset3
1) "two"
2) "one"
redis 127.0.0.1:6379> sunion myset2 myset3
1) "three"
2) "one"
3) "two"


sunionstore
返回所有给定key的并集
redis 127.0.0.1:6379> smembers myset2
1) "three"
2) "two"
redis 127.0.0.1:6379> smembers myset3
1) "two"
2) "one"
redis 127.0.0.1:6379> sunionstore myset 4 myset2 myset3
(integer) 3
redis 127.0.0.1:6379> smembers myset4
1) "three"
2) "one"
3) "two"


smove
从第一个key对应的set中移除member并添加到第二个对应的set中
redis 127.0.0.1:6379> smembers myset2
1) "three"
2) "two"
redis 127.0.0.1:6379> smembers myset3
1) "three"
2) "one"
redis 127.0.0.1:6379> smove myset2 myset7 three
(integer) 1
redis 127.0.0.1:6379> smembers myset2
1) "two"
redis 127.0.0.1:6379> smembers myset7
1) "three"


scard
返回名称为key的set的元素个数
redis 127.0.0.1:6379> scard myset2
(integer) 1


sismember
测试member是否是名称为key的set的元素
redis 127.0.0.1:6379> smembers myset2
1) "two"
redis 127.0.0.1:6379> sismember myset2 two
(integer) 1
redis 127.0.0.1:6379> sismember myset2 one
(integer) 0


srandmember
随机返回名称为key的set的一个元素,但不删除元素
redis 127.0.0.1:6379> smembers myset3
1) "two"
2) "one"
redis 127.0.0.1:6379> srandmember myset3
"two"
redis 127.0.0.1:6379> srandmember myset3
"one"


sorted sets 类型及操作
sorted set 是set的一个升级版本,它在set的基础上增加了一个顺序属性
这一属性在添加修改元素的时候可以指定
每次指定后,zset会自动重新按新的值调整顺序
可以理解为有两列的MySQL表,一列存value,一列存顺序,操作中key理解为zset的名字


zadd
向名称为key的zset中添加元素member,score用于排序,如果该元素存在,则更新其顺序
redis 127.0.0.1:6379> zadd myzset 1 "one"
(integer) 1
redis 127.0.0.1:6379> zadd myzset 2 "two"
(integer) 1
redis 127.0.0.1:6379> zadd myzset 3 "two" // 添加未成功,但是顺序号更新
(integer) 0
redis 127.0.0.1:6379> zrange myzset 0 -1 withscores // withscores 输出顺序号
1) "one"
2) "1"
3) "two"
4) "3"


zrem
删除名称为key的zset中的元素member
redis 127.0.0.1:6379> zrange myzset 0 -1 withscores
1) "one"
2) "1"
3) "two"
4) "3"
redis 127.0.0.1:6379> zrem myzset two
(integer) 1
redis 127.0.0.1:6379> zrange myzset 0 -1 withscores
1) "one"
2) "1"


zincrby
如果再名称为key的zset中已经存在元素member,则该元素的score增加increment
否则向该集合中添加该元素,其score的值为increment


redis 127.0.0.1:6379> zadd myzset2 1 "one"
(integer) 1
redis 127.0.0.1:6379> zadd myzset2 2 "two"
(integer) 1
redis 127.0.0.1:6379> zincrby myzset2 2 "one"
"3"
redis 127.0.0.1:6379> zrange myzset2 0 -1 withscores
1) "two"
2) "2"
3) "one"
4) "3"


zrank
返回名称为key的zset中member元素的排名(按score从小到大排序)即下标


redis 127.0.0.1:6379> zrange myzset3 0 -1 withscores
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
7) "five"
8) "5"
redis 127.0.0.1:6379> zrank myzset3 two
(integer) 1


zrevrank
返回名称为key的zset中member元素的排名(按score从大到小排序)即下标


redis 127.0.0.1:6379> zrange myzset3 0 -1 withscores
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
7) "five"
8) "5"
redis 127.0.0.1:6379> zrevrank myzset3 two
(integer) 2


zrevrange
返回名称为key的zset(按score从大到小顺序)中的index从start到end的所有元素


redis 127.0.0.1:6379> zrevrange myzset3 0 -1 withscores
1) "five"
2) "5"
3) "three"
4) "3"
5) "two"
6) "2"
7) "one"
8) "1"


zrangebyscore
返回集合中score在给定区间的元素


redis 127.0.0.1:6379> zrange myzset3 0 -1 withscores
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
redis 127.0.0.1:6379> zrangebyscore myzset3 2 3 withscores
1) "two"
2) "2"
3) "three"
4) "3"


zcount
返回集合中score在给定区间的数量
redis 127.0.0.1:6379> zrange myzset3 0 -1 withscores
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
7) "five"
8) "5"
redis 127.0.0.1:6379> zcount myzset3 2 3
(integer) 2


zcard
返回所有元素个数


redis 127.0.0.1:6379> zcard myzset3
(integer) 4


zremrangebyrank
删除集合中排名在给定区间的元素


redis 127.0.0.1:6379> zrange myzset3 0 -1 withscores
1) "one"
2) "1"
3) "two"
4) "2"
redis 127.0.0.1:6379> zremrangebyrank myzset3 1 1 
(integer) 1
redis 127.0.0.1:6379> zrange myzset3 0 -1 withscores
1) "one"
2) "1"


zremrangebyscore
删除集合中score在给定区间的元素


redis 127.0.0.1:6379> zrange myzset3 0 -1 withscores
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
redis 127.0.0.1:6379> zremrangebyscore myzset3 1 2
(integer) 2
redis 127.0.0.1:6379> zrange myzset3 0 -1 withscores
1) "three"
2) "3"


redis常用命令
1.键值相关命令


keys
返回满足给定pattern的所有key
表达式
代表取出所有的key 
redis 127.0.0.1:6379> keys
1) "myzset2"
2) "myzset3"
3) "mylist"
4) "myset2"
5) "myset3"
6) "myset4"
7) "k_zs_1"


exists
确认一个key是否存在 存在返回1 不存在返回0
redis 127.0.0.1:6379> exists name
(integer) 0 
redis 127.0.0.1:6379> exists age
(integer) 1


del
删除一个key
redis 127.0.0.1:6379> del age
(integer) 1
redis 127.0.0.1:6379> exists age
(integer) 0


expire
设置一个key的过期时间
在本例中,我们设置addr这个key的过期时间是10秒
然后我们不断的用ttl来获取这个key的有效时长,直至为-1
说明此值已过期


redis 127.0.0.1:6379> expire addr 10
(integer) 1
redis 127.0.0.1:6379> ttl addr
(integer) 8
redis 127.0.0.1:6379> ttl addr
(integer) 1
redis 127.0.0.1:6379> ttl addr
(integer) -1


move
将当前数据库中的key转移到其它数据库中


数据库有16个,从0-15
select 0 表示选择第0个数据库,默认的就是第0个数据库
redis 127.0.0.1:6379> select 0
redis 127.0.0.1:6379> set age 20
redis 127.0.0.1:6379> get age
1) "20"
redis 127.0.0.1:6379> move age 1
redis 127.0.0.1:6379> get age
(nil)
redis 127.0.0.1:6379> select 1
redis 127.0.0.1:6379> get age
1) "20"
redis 127.0.0.1:6379> select 0


persist
移除给定key的过期时间 结果中的-1代表取消过期时间,而不是已经过期
redis 127.0.0.1:6379> expire age 300
(integer) 1
redis 127.0.0.1:6379> ttl age
(integer) 294
redis 127.0.0.1:6379> persist age
(integer) 1
redis 127.0.0.1:6379> ttl age
(integer) -1


randomkey
随机返回key空间的一个key
redis 127.0.0.1:6379> randomkey
"mylist7"
redis 127.0.0.1:6379> randomkey
"mylist5"


rename
重命名key
redis 127.0.0.1:6379> keys

1) "age"
redis 127.0.0.1:6379> rename age age_new
OK
redis 127.0.0.1:6379> keys
1) "age_new"


type
返回值的类型
redis 127.0.0.1:6379> type addr
string
redis 127.0.0.1:6379> type myzset2
zset
redis 127.0.0.1:6379> type mylist
list




2.服务器相关命令


ping
测试连接是否存活
该案例 第一个ping时,说明此连接正常
第二个ping之前,将redis服务器停止,那么ping是失败的
第三个ping之前,将redis服务器启动,那么ping是成功的


redis 127.0.0.1:6379> ping
PONG
redis 127.0.0.1:6379> ping
Could not connect to Redis at 127.0.0.1:6379:Connect refused
not connected>ping
PONG
redis 127.0.0.1:6379> 


echo
在命令行打印一些内容
redis 127.0.0.1:6379> echo lijie
"lijie"


select
选择数据库 redis数据库编号从0-15
我们可以选择任意一个数据库来进行数据的存取
redis 127.0.0.1:6379> select 1
ok
redis 127.0.0.1:6379[1]> select 16
(error) ERR invalid DB index
redis 127.0.0.1:6379[16]>
当选择16时,报错,说明没有编号为16的这个数据库


quit
退出连接
redis 127.0.0.1:6379> quit
[root@localhost redis-2.2.12]#


dbsize
返回当前数据库中key的数目
redis 127.0.0.1:6379> dbsize
(integer) 18
结果说明此库中有18个key


info
获取服务器的信息和统计


config get
实时传储收到的请求
redis 127.0.0.1:6379> config get addr
1) "dir"
2) "/root/4setup/redis-2.2.12"
本例中我们获取了dir这个参数配置的值
如果想获取全部参数的配置值,只需要执行 config get
,即可将全部的值都显示出来


flushdb
删除当前选择数据库中的所有key
redis 127.0.0.1:6379> dbsize
(integer) 18
redis 127.0.0.1:6379> flushdb
ok
redis 127.0.0.1:6379> dbsize
(integer) 0
在本例中我们将0号数据库中的key都清除了


flushall
删除所有数据库中的所有key
在本例中先查看了一个1号数据库中有一个key
然后切换到0号数据库执行flushall命令
结果1号库中的key也清除了
redis 127.0.0.1:6379[1]> dbsize
(integer) 1
redis 127.0.0.1:6379[1]> select 0
ok
redis 127.0.0.1:6379> flushall
ok
redis 127.0.0.1:6379> dbsize
(integer) 0
redis 127.0.0.1:6379> select 1
ok
redis 127.0.0.1:6379[1]> dbsize
(integer) 0


Redis 高级实用特性
1.安全性
设置客户端连接后进行任何其他指定前需要使用的密码
警告:因为redis速度相当快,所以在一台比较好的服务器下,一个外部的用户可以在一秒钟进行150K次的密码尝试
这意味着你需要指定非常非常强大的密码来防止暴力破解


修改密码:
在redis-conf配置文件中修改
# requirepass foobared
requirepass beijing
修改密码后需要重启redis
关闭redis
pkill redis-server


启动一个客户端
[root@localhost redis-2.2.12]# src/redis-cli
redis 127.0.0.1:6379> keys
(error) ERR operation not permitted
这里显示权限被禁止,我们来设置一下权限
redis 127.0.0.1:6379> auth beijing
ok
redis 127.0.0.1:6379> keys

1) "name"


如果不想每次执行命令的时候都输入授权信息
在登陆的时候就指定授权信息
[root@localhost redis-2.2.12]# src/redis-cli -a beijing
redis 127.0.0.1:6379> keys *
1) "name"


2.主从复制


Redis 主从复制配置和使用都非常简单
通过主从复制可以允许多个slave server 拥有和 master server 相同的数据库副本


Redis主从复制特点:
1)master可以拥有多个slave
2)多个slave可以连接同一个master外,还可以连接到其他slave
3)主从复制不会阻塞master,在同步数据时,master可以继续处理client请求
4)提高系统的伸缩性


redis主从复制过程:
1)slave与master建立连接,发送sync同步命令
2)master会启动一个后台进程,将数据库快照保存到文件中,同时master主进程会开始收集新的写命令并缓存
3)后台完成保存后,就将此文件发送给slave
4)slave将此文件保存到硬盘上


配置主从服务器:
配置slave服务器很简单,只需要在slave的配置文件中加入如下配置:
slaveof 192.168.1.1 6379 # 指定master的ip和端口
masterauth lamp # 这是主机的密码
如何判断哪个是master哪个是slave
只需要调用info就可以得到主从的信息
在从库执行info
redis 127.0.0.1:6379> info
role:slave
master_host:localhost
master_port:6379
master_link_status:up
master_last_io_seconds_ago:10
master_sync_in_progress:0
db0:keys=1,expires=0
主服务器上执行info
role:master




3.事务处理
redis对事务的支持目前还比较简单,redis只能保证一个client发起的事务中的命令可以连续的执行
而中间不会插入其他client的命令
当一个client在一个连接中发出multi命令时,这个连接会进入一个事务上下文
该连接后续的命令不会立即执行
而是先放到一个队列中,当执行exec命令时,redis会顺序的执行队列中的所有命令


简单事务处理
redis 127.0.0.1:6379> get age
"33"
redis 127.0.0.1:6379> multi
ok
redis 127.0.0.1:6379> set age 10
QUEUED
redis 127.0.0.1:6379> set age 20
QUEUED
redis 127.0.0.1:6379> exec
1) ok
2) ok
redis 127.0.0.1:6379> get age
"20"


如何取消一个事务
该案例可以发现这次2个 set age 命令都没有被执行
discard命令其实就是清空事务的命令队列并退出事务上下文
也就是我们常说的事务回滚
redis 127.0.0.1:6379> get age
"20"
redis 127.0.0.1:6379> multi
ok
redis 127.0.0.1:6379> set age 33
QUEUED
redis 127.0.0.1:6379> set age 10
QUEUED
redis 127.0.0.1:6379> discard
ok
redis 127.0.0.1:6379> get age 
"20"


redis的事务,如果事务中某个命令出现错误不会回滚


乐观锁复杂事务控制
乐观锁:大多数是基于数据版本(version)的记录机制实现的
即为数据增加一个版本标识,在基于数据库表的版本解决方案中,
一般是通过为数据库表增加一个version字段来实现读取出数据时,
将此版本号一同读出,之后更新时,对此版本号加1
此时,将提交数据的版本号与数据库表对应记录的当前版本号进行比对
如果提交的数据版本号大于数据库当前版本号,则予以更新,否则认为是过期数据


redis乐观锁实例:
假设有一个age的key,我们开2个session来对age进行赋值操作,我们来看一下结果如何
(1) 第1步 session1
redis 127.0.0.1:6379> get age
"10"
redis 127.0.0.1:6379> watch age # 代表对age进行监控
ok
redis 127.0.0.1:6379> multi
ok
(2) 第2步 session2
redis 127.0.0.1:6379> set age 30
ok
redis 127.0.0.1:6379> get age
"30"
(3) 第3步 session1
redis 127.0.0.1:6379> set age 20
QUEUED
redis 127.0.0.1:6379> exec
(nil)
redis 127.0.0.1:6379> get age 
"30"


watch命令会监视给定的key,当exec时候,如果监视的key从调用watch后发生过变化
则整个事务会失败
也可以调用watch多次监视多个key,这样就可以对指定的key加乐观锁了
注意:watch的key 是对整个连接有效的,事务也一样
如果连接断开,监视和事务都会被自动清除
当然了exec,discard,unwatch命令都会清除连接中的所有监视


事务回滚
redis的事务实现是如此简单,当然会存在一些问题
第一个问题是redis只能保证事务的每个命令连续执行
但是如果事务中的一个命令失败了,并不回滚其他命令
比如使用的命令类型不匹配


4.持久化机制


redis是一个支持持久化的内存数据库,也就是说redis需要经常将内存中的数据同步到硬盘来保证持久化


redis支持2种持久化方式:
1)snapshotting(快照)也是默认方式
2)Append-only file (缩写aof)的方式


Snapshotting方式
快照是默认的持久化方式
这种方式是将内存中数据以快照的方式写入到二进制文件中
默认的文件名为dump.rdb
可以通过配置设置自动做快照持久化的方式
我们可以配置redis在n秒内如果超过m个key被修改就自动做快照
save 900 1 # 900秒内如果超过1个key被修改,则发起快照保存
save 300 10 # 300秒内如果超过10个key被修改,则发起快照保存
save 60 10000


aof方式
由于快照方式是在一定间隔时间做一次的,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改
aof比快照方式有更好的持久化性,
是由于在使用aof时,redis会将每一个收到的写命令都通过write函数追加到文件中
当redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容
当然,由于os会在内核中缓存write做的修改,
所以可能不是立即写到磁盘上,这样aof方式的持久化也还是有可能会丢失部分修改
可以通过配置文件告诉redis我们想要通过fsync函数强制os写入到磁盘的时机
appendonly yes // 启用aof持久化方式
# appendfsync always // 收到写命令就立即写入磁盘,最慢,但是保证完全的持久化
appendfsync everysec // 每秒钟写入磁盘一次,在性能和持久化方面做了很好的折中
# appendfsync no // 完全依赖os,性能最好,持久化没保证


5.发布订阅消息


发布订阅(pub/sub)是一种消息通信模式,主要的目的是解除消息发布者和消息订阅者之间的耦合
redis作为一个pub/sub的server,在订阅者和发布者之间起到了消息路由的功能
订阅者可以通过subscribe和psubscribe命令向redis server 订阅自己感兴趣的消息类型
redis将消息类型称为通道(channel)
当发布者通过publish命令向redis server发送特定类型的信息时
订阅该信息类型的全部client都会收到此消息


6.虚拟内存的使用


redis的虚拟内存与操作系统的虚拟内存不是一回事
但是思路和目的都是相同的
就是暂时把不经常访问的数据从内存交换到磁盘中,从而腾出宝贵的内存空间用于其他需要访问的数据
尤其是对于redis这样的内存数据库,内存总是不够用的
除了可以将数据分割到多个redis server外
另外能够提高数据库容量的办法就是使用虚拟内存把那些不经常访问的数据交换到磁盘上


虚拟内存配置
下面是vm相关配置
vm-enabled yes # 开启vm功能
really-use-vm yes
vm-swap-file /tmp/redis.swap # 交换出来的value保存的文件路径
vm-max-memory 1000000 # redis使用的最大内存上线
vm-page-size 32 # 每个页面的大小32字节
vm-pages 134217728 # 最多使用多少页面
vm-max-threads 4 # 用于执行value对象换入缓存的工作线程数量


php支持redis
首先下载phpredis源码包
解压缩 tar zxvf phpredis.tar.gz
进入phpredis文件夹
给phpredis准备一个编译环境
/usr/local/php/bin/phpize
如果出现错误:


编译安装
./configure --with-php-config=/usr/local/php/bin/php-config
make
/usr/local/php/include/php/Zend/../TSRM/TSRM.h:165:26: error: redefinition of pa                                                                                        rameter ‘tsrm_ls’
遇到这个错误


没解决,好惆怅 :-(




make install


cd /usr/local/php//lib/php/extensions/no-debug-zts-20121212/
找到 redis.so


打开php.ini
加上
extension=redis.so
保存退出,重启