redis 是一个基于内存的高性能key-value数据库,数据都保存在内存中定期刷新到磁盘,以极高的读写效率而备受关注。他的特点是支持各种数据结构,stirng,hashes, list,set,和sorted sets
1、下载安装
wget http://download.redis.io/redis-stable.tar.gz
tar -zxvf redis-stable.tar.gz
cd redis-stable
make
make test 检查一下是否正常,遇到2个错误
[root@localhost redis-stable]# make test
cd src && make test
make[1]: Entering directory `/usr/local/src/redis-stable/src'
which: no tclsh8.5 in (/usr/lib64/qt-3.3/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/geffzhang/bin)
You need 'tclsh8.5' in order to run the Redis test
make[1]: *** [test] 错误 1
make[1]: Leaving directory `/usr/local/src/redis-stable/src'
make: *** [test] 错误 2
[root@localhost redis-stable]#
没安装tcl
按照官网http://www.linuxfromscratch.org/blfs/view/cvs/general/tcl.html 上的安装
make install
mkdir -p /usr/local/bin
cp -pf redis-server /usr/local/bin
cp -pf redis-benchmark /usr/local/bin
cp -pf redis-cli /usr/local/bin
cp -pf redis-check-dump /usr/local/bin
cp -pf redis-check-aof /usr/local/bin
make[1]: Leaving directory `/usr/local/src/redis-stable/src'
[root@localhost redis-stable]#
好了,现在redis就安装成功了
Redis 由四个可执行文件:redis-benchmark、redis-cli、redis-server、redis-stat 这四个文件,加上一个redis.conf就构成了整个redis的最终可用包。它们的作用如下:
- redis-server:Redis服务器的daemon启动程序
- redis-cli:Redis命令行操作工具。当然,你也可以用telnet根据其纯文本协议来操作
- redis-benchmark:Redis性能测试工具,测试Redis在你的系统及你的配置下的读写性能
- redis-stat:Redis状态检测工具,可以检测Redis当前状态参数及延迟状况
现在就可以启动redis了,redis只有一个启动参数,就是他的配置文件路径。
redis-server /etc/redis.conf
注意,默认复制过去的redis.conf文件的daemonize参数为no,所以redis不会在后台运行,这时要测试,我们需要重新开一个终端。修改为yes则为后台运行redis。另外配置文件中规定了pid文件,log文件和数据文件的地址,如果有需要先修改,默认log信息定向到stdout.
下面是redis.conf的主要配置参数的意义:
- daemonize:是否以后台daemon方式运行
- pidfile:pid文件位置
- port:监听的端口号
- timeout:请求超时时间
- loglevel:log信息级别
- logfile:log文件位置
- databases:开启数据库的数量
- save * *:保存快照的频率,第一个*表示多长时间,第三个*表示执行多少次写操作。在一定时间内执行一定数量的写操作时,自动保存快照。可设置多个条件。
- rdbcompression:是否使用压缩
- dbfilename:数据快照文件名(只是文件名,不包括目录)
- dir:数据快照的保存目录(这个是目录)
- appendonly:是否开启appendonlylog,开启的话每次写操作会记一条log,这会提高数据抗风险能力,但影响效率。
- appendfsync:appendonlylog如何同步到磁盘(三个选项,分别是每次写都强制调用fsync、每秒启用一次fsync、不调用fsync等待系统自己同步)
这时你可以打开一个终端进行测试了,配置文件中默认的监听端口是6379
2、建立用户和日志目录
第一次启动时建议为Redis建立用户和日志目录
[root@localhost redis-stable]# useradd redis
[root@localhost redis-stable]# mkdir -p /var/lib/redis
#db文件放在这里,需要修改redis.conf
# The working directory.
#
# The DB will be written inside this directory, with the filename specified
# above using the 'dbfilename' configuration directive.
#
# Also the Append Only File will be created inside this directory.
#
# Note that you must specify a directory here, not a file name.
dir /var/lib/redis
[root@localhost redis-stable]# mkdir -p /var/log/redis
# Specify the log file name. Also 'stdout' can be used to force
# Redis to log on the standard output. Note that if you use standard
# output for logging but daemonize, logs will be sent to /dev/null
logfile /var/log/redis/redislog
[root@localhost redis-stable]# chown redis.redis /var/lib/redis
[root@localhost redis-stable]# chown redis.redis /var/log/redis
3、配置Init脚本
Redis管理脚本基于Ubuntu 的发行版上的,Ubuntu的可以看这篇文章ubuntu安装启动redis,在Centos linux 上并不能用,下面有个脚本可以用于CentOS 。
用这个脚本管理之前,需要先配置下面的内核参数,否则Redis脚本在重启或停止redis时,将会报错,并且不能自动在停止服务前同步数据到磁盘上:
# vi /etc/sysctl.conf
vm.overcommit_memory = 1
然后应用生效:
# sysctl –p
建立redis启动脚本:
# vim /etc/init.d/redis
#!/bin/bash
#
# Init file for redis
#
# chkconfig: - 80 12
# description: redis daemon
#
# processname: redis
# config: /etc/redis.conf
# pidfile: /var/run/redis.pid
source /etc/init.d/functions
#BIN="/usr/local/bin"
BIN="/usr/local/bin"
CONFIG="/etc/redis.conf"
PIDFILE="/var/run/redis.pid"
### Read configuration
[ -r "$SYSCONFIG" ] && source "$SYSCONFIG"
RETVAL=0
prog="redis-server"
desc="Redis Server"
start() {
if [ -e $PIDFILE ];then
echo "$desc already running...."
exit 1
fi
echo -n $"Starting $desc: "
daemon $BIN/$prog $CONFIG
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog
return $RETVAL
}
stop() {
echo -n $"Stop $desc: "
killproc $prog
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog $PIDFILE
return $RETVAL
}
restart() {
stop
最近对MongoDB进行了一些研究,我认为其很实用,很有发展前途。
对于关系数据库的使用,大家普遍认为JOIN操作开销很大,所以在设计的过程中,就极力避免这类操作。
一般在设计上遵循了关系数据库中“范式”的概念,而操作数据大部分都是针对单表的。
即使有JOIN的需求,也是通过应用程序分两步或多步获取数据。
以“私信”应用的收件箱为例(以下设计有简化):
收件箱:
create table inbox(
uid int unsigned not null, //收件人的uid
mid int unsigned not null, //私信的唯一标识mid
time timestamp not null default current_timestamp, //收信时间
primary key(uid,mid)
)engine=innodb;
信件内容:
create table msg(
mid int unsigned not null auto_increment, //私信的唯一标识mid
content blob not null, //私信内容
primary key(mid)
)engine=innodb;
如果使用JOIN来获取消息列表:
select inbox.mid,inbox.time,msg.content from inbox join msg on inbox.mid=msg.mid where inbox.uid=:uid order by inbox.mid desc limit 10;
如此使用JOIN操作,不利于两个数据表的拆分。
一般情况,我们会msg数据表中的数据根据mid进行拆分并使用Memcache等进行缓存。而对于inbox数据表,我们会根据uid进行拆分。这样我们的应用程序需要分两步获取最终列表数据:
1,select mid from inbox where uid=:uid order by mid limit 10;
2,使用上一步获得的mid,在Memcache中获取content数据。
根据我的经验,大部分现代互联网应用,并没有将关系数据库当作一个“关系”数据库来使用。
MongoDB基本实现了我们对于数据库中单表操作的所有需求,并且在某些方面有独特的优势。
以下简单列举MongoDB的一些特性:
1,在MongoDB中,一条数据以JSON编码的字符串体现,以BSON编码的数据存储。
2,由于其存储格式灵活,所以增删数据列,无需漫长的alter table操作。
3,每个数据表(在MongoDB中叫做Collection)都需要有主键。
4,支持Secondary index,支持多列索引(where a=1 and b=2),支持排序( order by time desc)。
5,使用简单的的非SQL指令对数据进行CRUD操作,并支持丰富的操作符,比如$inc对某一列数值进行增加操作。
6,实现简单master-slave复制,也支持Replica Sets(自动选举master)。
7,实现自动数据切分 auto sharding。
8,实现了简单的data proxy功能,数据拆分对应用透明。
以上大部分特性是我们在实际应用中对数据库管理系统(DBMS)最实用、最迫切的需求。
更重要的是,MongoDB使用C++语言编写,源代码只有1.5M左右,相对于MySQL的30M的源代码,更容易学习和维护。
通过我对多种号称“NOSQL”的非关系型数据库系统的研究,我认为MongoDB是最实用、最有前途的产品之一。
目前有独立的公司(10gen)为mongoDB提供商业技术支持,已经有数百家互联网公司在生产环境中部署MongoDB。
非关系型数据库是未来互联网应用中的一个技术趋势,我们要在将来能够立足,就必须未雨绸缪。
所以我认为我们应该从现在开始学习,并逐步在实践中积累经验。
目前MongoDB的学习资料主要有:
1,官方文档: http://www.mongodb.org/display/DOCS/Home
2,O'Reilly出版的权威指南: http://oreilly.com/catalog/0636920001096
当然,最好的学习途径就是实践,最好能够找一个应用来实战。
通过实战,可以在部署、开发、运维等方面积累最宝贵的经验。
本文链接
Fqueue是一个非常轻量级、高性能的开源队列服务器,地址:http://code.google.com/p/fqueue/。下面是我在adev淘宝技术嘉年华上分享的《高性能队列Fqueue的设计和使用实践》PPT.
图1 这是总体架构图
图2 这是内部存储的原理图
有任何问题可以和我微博交流,也可以到Fqueue主页上提交问题。
另外去哪儿网大量招聘靠谱的技术人员(java,dba,运维),可以把简历发给我li.sunATqunar.com(AT换成@)
下面是全部的PPT
在很多地方都有“数据交换”这个概念,本文所说的“数据交换” 是指在计算机网络中,一个系统把数据传递给另外一个系统。这非常类似于一个人要告诉另外一个人一件事情。
当一个人要把一件事情告诉另外一个人的时候,我们可以通过电话、邮件、短信、IM工具或者当面说的方式来交流。这种方式类似于系统数据交换要通过 tcp、udp、管道等等的方式实现。当两个人交流的时候,我们需要一种共同的语言才能明白对方的意思,同样的,两个系统要交换数据,也需要定义一种双方都明白的协议,我们称为“数据交换协议”。
数据交换协议数据交换协议的目的是让两个系统进行正确的数据交互。所以几乎各种开发语言都提供了方便使用的数据交换功能。比如说使用JAVA语言的开发的系统使用 MySQL数据库存储数据,就是通过MySQL数据交换协议跟MySQL做数据交换;通过JAVA的RMI可以方便的做跨机器的分布式数据交换,RMI也就是一种数据交换协议。
一般我们在不同的系统、不同的语言之间交换数据的时候,我们会选择一种通用的交换协议或者自己定义一种容易使用的交换协议。 WebService曾经非常流行, 在Web 2.0时代,轻量级的REST协议又开始受到追捧。那么究竟在我们的系统中应该选择什么样的协议呢?
如何选择数据交换协议选择什么样的协议跟我们的应用场景有很大的关系。我们需要考虑我们开发是否方便、接口是否容易发布、是否需要考虑带宽占用成本、序列化和反序列化的性能、接口协议的扩展性等等。下面我们看下几个比较常用的交换协议实现。
协议实现跨语言性能传输量RPCxml广泛几乎所有 低很大N(可实现)json广泛大量一般一般N(可实现)php serializePHPRPC大量一般一般Yhessianhessian大量一般小Ythriftthrift大量高小Yprotobufprotobuf大量高小N(可实现)iceice大量高小YavroApache Avro少量高小Ymessagepackmessagepack 大量高小Y上面表格列出了一些常用数据交换协议的一些特性的比较。这里并没有比较好坏,只是想说明不同数据交换协议是有区别的,所以我们需要在我们的应用场景中进行选择。
开放式像微博,SNS这种开放平台、对静态html页面提供javascript接口调用的系统都属于这种类型 。这种类型的特点是:
- 调用方不完全可控,而且是针对公网的,你可能不知道是谁、是什么语言、是什么方式在调用你提供的数据接口;
- 接口访问量一般都非常大,要求具有很高的性能和吞吐量;
- 需要考虑安全问题,外部提交的数据可能不是合法的。
所以在这种情况下,需要考虑数据传输的带宽消耗和数据交换协议的易用性,以及多语言支持程度。以前对于html页面使用的javascript接口调用一般都使用XML格式,最近几年几乎都转成了json格式了,因为json传输量更小,比XML更加容易使用。 而对于开放平台,由于使用的场景很多,所以需要提供多种交换协议格式。基本上都会提供XML和json。为了提高平台本身的性能和客户端的性能,也可以提供protobuf这种二进制交换协议并且增加压缩支持,以节省带宽传输和解析的性能消耗。
内部服务对于一个大型系统来说,内部服务的数据交换无处不在。从最基本和常见的数据库数据交换、memcached缓存数据交换、消息队列的数据交换到系统之间使用的RPC服务框架等等,都可以算作内部服务的数据交换。内部服务的特点是不用考虑防火墙,不对外开放,速度快(基本无带宽成本)。
内部服务的数据交换协议的选择空间非常大,一般需要考虑:
- 数据交换协议的性能
- 是否需要跨语言支持
- 数据交换协议的消息体大小
对于持久化存储来说,每一种数据交换协议其实都可以实现。一般需要根据应用场景考虑:
- 是否人工可阅读
- 存储的空间消耗
- 序列化和反序列化的性能
- 是否经过压缩
假设我们的网站前端页面展示层使用PHP语言开发,中间业务逻辑使用JAVA语言开发,那么就涉及到跨语言数据交换的问题。只要系统不是单纯的使用一种语言,那么就必须考虑这个问题。事实上,考虑未来的扩展和需求变化问题,也最好考虑跨语言的数据交互协议。
数据交换协议可升级在选择数据交换协议的时候,我们同样需要考虑类似于数据库表的?schema设计时的扩展问题。比如一个提供用户信息的数据交换协议接口,现在包含用户名、性别、住址的信息,在升级过程中,增加了一个最后登录的IP信息。如果不考虑数据交换协议升级带来的影响,很可能会导致以前的客户端出现异常或者旧的数据无法正确解析的问题。
兼容协议的巧用兼容协议的巧用非常有用,新产品兼容提供现有成熟的数据交换协议,可以降低使用门槛和产品的开发速度。比如新浪开源的memcacheQ就使用了memcached协议。
总结数据交换协议的各种通用开源实现非常多,数据交换协议只是一个非常宽泛的说法,其实只要实现了数据的序列化和反序列化 ,那么就可以说是一个可以交换数据的协议。数据交换协议的性能其实就是序列化和反序列化的性能,如果加上RPC,那么跟RPC实现本身的性能也有非常大的关系。
我的新浪微博@sunli1223 ,欢