根据某学习视频所记录的笔记:
一、NOsql适用场景:
1.对数据高并发读写
2.对海量数据的高效率存储和访问
3.对数据的高扩展性和高可用性
二、Redis的介绍
Redis是一个开源的,先进的Key-Value存储。它通常被称为数据结构服务器,因为键可以包含字符串、哈希、链表、集合和有序集合。这些数据类型都支持push/pop、add/remove及取交集和并集及更丰富的操作,Redis支持各种不同方式的排序。为了保证效率,数据都是缓存在内存中的,它可以周期性的把更新的数据写入磁盘或者把修改的操作写入追加的记录文件。
全球最大的Redis用户是新浪微博,在新浪有200多台物理机,400多个端口正在运行着Redis,有+4G的数据在Redis上位微博用户提供服务。在新浪微博Redis的部署场景很多,大概分为以下2中:
1.应用程序直接访问Redis数据库:写MysqL,通过触发器更新Redis的方式
不安全,Redis服务器宕机,或者内存中的数据被释放了,数据就永久丢失了
2.应用程序直接访问Redis,只有当Redis访问失败时才访问MysqL
三、Redis具体适用场合:
1.取最新N个数据的操作
2.排行榜应用,取TOP N操作
3.需要精确设定过期时间的应用
4.计数器应用
5.Uniq操作,获取某段时间所有数据排重值
6.实时系统,反垃圾系统
7.pub/sub(发布/订阅)构建实时消息系统
8.构建队列系统
9.缓存
四、Redis的安装部署(32-UbuntuLinux下)
1.下载安装包:
wget http://redis.googlecode.com/files/redis-2.6.14.tar.gz
手动下载地址:http://download.csdn.net/detail/chc340121/8164989
2.编译源程序:
tar -zxvfredis-2.6.14.tar.gz
cdredis-2.6.14
make
cd src && make install
3.移动文件,便于管理
redis-2.6.14/src# mv ../redis.conf /usr/local/redis/etc/
redis-2.6.14/src# mv mkreleasehdr.sh redis-benchmark redis-check-aof redis-check-dump redis-cli redis-server /usr/local/redis/bin/
4.启动Redis服务器:
启动时要制指定一个配置文件,启动成功后画面如下:
Redis服务端的默认连接端口是6379
5.客户端连接:
chc@myDesk:~$ /usr/local/redis/bin/redis-cli
redis 127.0.0.1:6379>
6.停止Redis实例:
/usr/local/redis/bin/redis-cli shutdown或pkill redis-server
(ps -ef | grep redis查看redis服务进程;netstat -tunpl | grep 6379查看某一端口的占用情况)
7.Redis的配置:
daemonize 默认为no,如果需要在后台运行,把该项设为yes
pidfile配置多个pid的地址,默认在/var/run/redis.pid
bind 绑定IP,设置后只接受来自该IP的请求
port 监听端口,默认为6379
timeout 设置客户端连接时的超时时间,单位为秒
loglevel 分为4级,debug、verbose、notice、warning
logfile 配置log文件地址
save 设置Redis进行数据库镜像的频率
rdbcompression 在进行镜像文件备份时,是否进行压缩
Masterauth 主数据库连接时需要的验证密码
Maxclients 限制同时连接的客户数量
maxmemory 设置redis能够使用的最大内存
Appendonly 开启append only 模式
Appendfsync 设置对appendonly.aof文件同步的频率
va-enabled 是否开启虚拟内存支持
vm-swap-file 设置虚拟内存的交换文件位置
vm-max-memory 设置redis使用的最大物理内存大小
vm-page-size 设置虚拟内存的页大小
va-max-threads 设置VMIO同时使用的线程数量
Glueoutputbuf 把小的输出缓存存放在一起
Hash-max-zipmap-entries 设置hash的临界值
Activerehashing 重新hash
五、Redis的数据类型
1、String类型及操作
String是最简单的类型,一个key对应一个value,String类型是二进制安全的。Redis的string可以包含任何数据,比如jpg图片或者序列化的对象。
操作:
set 设置对应的值为string类型的value,如果键已存在则覆盖原有的值;
例如:添加一个name=chc的键值对
redis 127.0.0.1:6379> set nane chc
setnx 设置对应的值为string类型的value,如果key已经存在,则返回0,nx是not exst的意思
setex 设置对应的值为string类型的value,并指定此键值对应的有效期,如setex name 10 chc,10秒后name将消失
setrange 设置指定key的value值得子字符串;如,希望将xxx@126.com 替换为gmail邮箱,setrange email 4 gmail.com--->get email -->xxx@gmail.com
mset 一次设置多个key的值,成功返回ok表示所有的值都设置了;失败返回0表示没有任何值被设置。如mset name chc age 24 sex man
msetnx一次设置多个key的值,成功返回ok表示所有的值都设置了;失败返回0表示没有任何值被设置,但是不会覆盖已经存在的key。
get 获取key对应的string值,如果key不村子返回nil
getset设置key的值,并返回key的旧值
getrange 获取key的value值得子字符串,如getrange name 0 5
mget 一次性获取多个key的值,如果key不存在则对应返回nil
incr 对key的值做加加操作,并返回新的值。
incrby 同incr类似,加指定值,key不存在时会设置key,并认为原来value是0;
decr对key的值做减减操作;
decrby同decr类似,减指定值;
append 给指定key的字符串追加value,返回新字符串的长度;
strlen 取指定key的value值得长度;
2.hash类型及操作
Redis hash是一个string类型的field和value的映射表。它的添加、删除操作都是O(1)。hash特别适合于存储对象,相较于将对象的每个字段存成单个string类型,讲一个对象存储在hash类型中会占用更少的内存,并且可以哈、更方便的存取整个对象。
hset 设置hash field为指定值,如果key不存在则先创建;如hset myhash field1 hello;
hsetnx、hmset、hget、hmget、hincrby(如hincrby myhash age -2)、hexist(测试指定field是否存在,存在就返回1,否则返回0 )、hlen'(返回指定hash的field数量)
hdel(删除指定hash的field,删除成功返回1,否则返回0)、hkeys(返回hash所有的field)、hvals(返回hash的所有value)、hgetall(获取某个hash中全部的field及其value)
3.list类型及操作
List是一个链表结构,主要功能是pus、pop、获取一个范围的所有值等等,操作中的key理解为链表的名字。Redis的list类型起始就是一个每个子元素都是string类型的双向链表。我们可以通过push、pop操作从链表的头部或尾部添加删除元素,这样list既可以作为栈又可以作为队列。
lpush 在key对应list的头部添加字符串元素并返回list中的元素个数,如lpush mylist “hello”;
lrange lrange mylist headIndex tailIndex;lrange mylist 0 -1;0代表头部第一个元素,-1代表尾部第一个元素
rpush 在key对应list的尾部添加字符串元素;
linsert 在key对应list的特定位置前或后添加字符串:(由尾到头方向为前 )
lset 设置list中指定下标的元素值,如rpush mylist “hello” , lset mylist 0 “world”;
lrem 从key对应list中删除n个和value相同的元素,返回删除的个数(n<0从尾部删,n=0全部删除);
ltrim 保留指定key的值范围内的数据,如ltrim mylist 2 -1
rpoplpush 从第一个list的尾部移除元素并添加到第二个list的头部:
lindex 返回名称为key的list中index位置的元素;
llen 返回list的长度;
4.set类型及其操作
set是集合,它是string类型的无序集合。set是通过hash table实现的,添加、删除和查找复杂度都是O(1)。对于集合我们可以取并集、交际、差集。通过这些操作我们可以实现sns中的好友推荐和blog的tag功能。
sadd 向名称为key的set中添加元素,set中已有的元素是加不进去的,加入成功返回1,否则返回0;
smembers 查看set下所有元素;
sdiff 返回所有给定key与第一个key的差集,如sdiff A B(即返回A-B,把A中有的而B中没有的元素返回):
sdiffstore A B C 将B与C的差集存到A中,且A是被重写的,以前A中的元素全被清空;
sinter 返回所有集合的交集;
sinterstore A B C 将B与C的交集存到A中,且A是被重写的,以前A中的元素全被清空;
sunion 返回所有集合的并集;
sunionstore A B C 将B与C的并集存到A中,且A是被重写的,以前A中的元素全被清空;
smove setA setB member从第一个集合中移除member加到第二个集合中;
scard 返回集合中元素的个数;
sismember setA member 测试member是否是集合A中的元素,是就返回1,否则返回0;
5.sorted set类型及操作
sorted set在set的基础上增加了一个顺序属性,这一属性在添加修改元素的时候可以指定,每次指定后,zset会自动重新安排新的值调整顺序。可以理解为有两列的MysqL表,一列存value,一列存顺序。操作中key理解为zset的名字。
zadd zsetA order member 向 向Zset中添加一个元素并指定其顺序:
zrange zsetA headindex tailindex withscores 将排序的序号也输出;
zrem、zincrby:
zrank 返回集合中元素的排名(按score从小到大排序)即下标:
zrevrank 返回集合中元素的排名(按score从大到小排序)即下标;
zrevrange 返回集合中的元素中的index从start到end的所有元素(按score从大到小排序);
zrangebyscore 返回集合中score从start到end的所有元素;
zcount zsetA start end返回集合中score在给定区间的数量;
zcard 返回集合中元素的个数;
zremrangebyrank zsetA start end按下标来排序,然后删除给定下标区间里的元素;
zremrangebyscore zsetA start end 按score来排序,然后删除给定scor区间里的元素;
六、Redis的常用命令
1.键值相关命令
keys 返回满足给定pattern的所有key;表达式 * 表示取出所有的key;
exists 确认一个key是否存在,若存在返回1,否则返回0;
del 删除一个key,成功返回1,否则返回0;
expire 设置一个key的过期时间,以秒为单位,可用ttl 查看某个键还有多长时间过期,-1表示已经过期:
persist 移除给定key的过期时间;
randomkey 随机返回key空间里的一个key;
rename 重命名key,rename old new;
type 返回key的数据类型;
2.服务器相关命令
ping 测试连接是否存活;
echo 在命令行打印一些内容;
select 选择数据库,Redis数据库编号从0~15,可以选择任意一个数据库来进行数据的存取;
quit/exit/ctrl+c 退出连接;
dbsize 返回当前数据库中key的数目;
config get [参数项名称] 获取某个参数项配置的值;
七、Redis的高级实用特性
1.安全性
设置客户端连接后进行其他指定前需要使用的密码。
Warning:因为redis速度相当快,所以在一台比较好的服务器下,一个外部用户可以在一秒钟进行150K次的密码尝试,这意味着你需要指定非常强大的密码来防止暴力破解。
在配置文件redis-config中设置requirepass password,然后重启redis server:
2.主从复制
Redis主从复制配置和使用都非常简单。通过主从复制可以允许多个slave server拥有和master server相同的数据库副本。其特点如下:
1)master可以拥有多个slave
2)多个slave可以连接同一个master外,还可以连接到其他slave
3)主从复制不会阻塞master,在同步数据时,master可以继续处理client请求
4)可以提高系统的伸缩性
过程:
1)slave与master建立连接,发送sync同步命令
2)master会启动一个后台进程,将数据库快照保存到文件中,同时master主进程会开始收集新的写命令并缓存
4)slave将此文件保存到硬盘
配置主从服务器:
只需在slave的配置文件中加入以下配置
slaveof IP Port #指定master的ip和端口
masterauth tiger #设置主机的密码
我使用的是在Oracle VM VirtualBox(虚拟机网络通信设置:http://www.xuebuyuan.com/830848.html)中的ubuntu虚拟机,然后复制了一份:
3.事务处理
Redis对事务的的支持目前还比较简单。Redis只能保证一个client发起的事务中的命令可以连续执行,而中间不会插入其他client的命令。当一个client在一个连接中发出multi命令时,这个链接会进入一个事务上下文,还连接后续的命令不会立即执行,而是先放到一个队列中,当执行exec命令时,redis会顺序执行队列中的所有命令。
------>>>>简单事务处理:
取消一个事务discard;队列中如果有一个命令执行出错,事务整体不会回滚。
乐观锁复杂事务控制:
乐观锁:大多数是基于数据版本的记录机制实现的。即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表添加一个version字段来实现,读取数据时,将此版本号一同读出,之后更新时,对此版本号加1.此时将提交数据的版本号与数据库表对应记录的当前版本号进行对比,如果提交数据的版本号大于数据库当前的版本号,则予以更新,否则认为是过期数据。
watch命令会调用监视给定的key,当exec时,如果监视的key从调用watch后发生改变,则整个事务会失败。也可以调用watch多次监视多个key。这样就可以对指定的key加乐观锁了。watch的key是对整个连接有效的,事务也一样。如果连接断开,监视和事务都会被自动清除。当然exec、discard、unwatch命令都会清楚连接中的所有监视。
4.持久化机制
Redis是一个支持持久化的内存数据库,即redis需要经常讲内存中的数据同步到硬盘来保证持久化。Redis支持两种持久化方式:
1)snapshotting(快照)也是默认方式--数据备份
快照方式是默认的持久化方式。这种方式是将内存中的数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb。可以通过配置设置做自动快照持久化的方式。
我们可以配置redis在n秒内如果超过m个key被修改就自动做快照。如:
save 600 1 #600秒内如果超过1个key被修改,则发起快照保存;
由于快照方式是在一定时间间隔做一次,所以如果redis意外down掉的话,就会丢失最后一次快照的所有修改。
aof比快照方式有更好的持久性是由于在使用aof时,redis会将每一个收到写命令都通过write函数追加到文件中,当redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。
2)Append-only file (缩写aof)的方式--将增删改操作存到文件中(类似于MysqL数据库的增量备份)
由于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将消息类型称为通道。当发布者通过publish命令向redis server发送特定类型的信息时,订阅该信息类型的全部client都会收到此信息。
6.虚拟内存的实用
Redis的虚拟内存与操作系统的虚拟内存不是一回事,但是思路和目的都是相同的。就是把不经常访问的数据从内存交换到磁盘中,从而腾出宝贵的内存空间用于其他需要访问的数据。尤其是对于redis这样的内存数据库,内存总是不够用。除了可以将数据分割到多个redis server外。另外能够提高数据库容量的办法就是使用虚拟内存把那些不经常访问的数据交换到磁盘上。