redis 介绍


1、redis 简介


   Remote Dictionary Server(Redis)是一个基于key-value键值对的持久化数据库存储系统,redis和大名鼎鼎的memcached缓存服务很像,但是redis支持的数据类型更加丰富,包括string(字符串)、list(链表)、set(集合)和zset(有序集合)等。

   这些数据类型都是支持push/php、add/remove及取交集、并集和差集以及更加丰富的操作,而且这些操作都是原子性的,在此基础上,redis还支持各种不同的排序,与memcached缓存服务一样,为了保证效率,数据都是缓存在内存中提供服务,和memcached不同的是,redis持久化缓存服务还会周期性把更新的数据写到磁盘已经把修改的操作记录追加到文件里记录,比memcached更有优势的是,redis还支持主从同步,这点很类似关系型数据库mysql。

   redis的出现在一定程度上弥补了memcached这类key-value内存缓存服务不足,在部分场合上可以对关系型数据库起到很好的补充作用。

   官网:http://www.redis.io/

2、redis特点

  a、key-value键值类型存储系统

  b、支持数据可靠存储及落地

  c、单进程单线程高可用服务器

  d、crash safe & recovery slow

  e、单机qps可以达到10w

  f、适合小数据量高速度读写访问  


3、redis优点

    a、性能很高:redis能支持超过10万每秒的读写频率

    b、丰富的数据类型:redis支持二进制的strings,lists,hashes,set已经ordered set等数据类型操作

    c、原子:redis的所有操作都是原子性的,同时redis还支持对几个操作全并后的原子性操作

    d、丰富的特性:redis还支持publish/subscribe(发布、订阅),通知key过期等待特性

    e、主从复制:redis支持异机主从复制

    f、和memcache不同redis可以持久化存储数据。数据还可存到硬盘中。

5、redis缺陷和陷阱

    a、系统运行有毛刺

    b、不同命令延迟差别大

    c、内存管理开销大

    d、buffer io 造成系统OOM


6、数据类型

  作为key-value型存储系统数据库,Redis提供了key和value的映射关系,但是,除了常规的数值或字符串,redis的键值还可以是下面形式之一,下面是redis最为常用的数据类型

   string 字符串类型

   list(链表)

   set(集合)

   zset(有序集合

   hash 哈希

7、redis持久化

 通常,redis将数据存储于内存中,或被配置为使用虚拟内存,通过两种方式可以实现数据持久化,使用快照(snapshot)的方式,将内存中的数据不断写入到磁盘,或使用类似MySQL的binlog日志(aof不用于主从同步)方式,记录每次更新的日志,前者性能较好,但是可能会引起一定程度的数据丢失,后者相反。

    建议:如果更新频繁,对数据的一致性要求高,使用AOF策略为主;如果是更新不频繁,可以容忍少量数据丢失或者错误,snapshot策略为主

8、redis的应用场景

     a、mysql+memcache架构架构问题


   传统的mysql+memcached的网站架构遇到的问题

   

   通过mysql数据库存储数据,加速通过memcached把热点数据存放到内存的cache里,达到加速数据访问减少数据库的压力,这是绝大多数公司都曾经或者正在使用的架构,但随着业务的不断增加,和访问量的持续增长,很多问题就会暴露出来:

    a、需要不断对mysql进行拆库拆表,memcached也需要不断跟着扩容,扩容和维护需要大量开发 和运维时间

    b、memcached和mysql数据库数据一致性问题也是个大难题

    c、memcached数据命中率低或宕机,会导致大量的访问直接穿透数据库,导致mysql数据库无法支撑访问

    d、跨机房cache同步一致性问题

   

    就有了下面redis的应用场景:

a、redis最佳试用场景是全部数据in-memory

b、redis更多场合作为memcached的代替品来使用

c、当需要除了key-value之外的更多数据类型支撑时,使用redis更加合适

d、支持持久化

e、需要负债均衡的场景

用在计算、cache服务、展示最近、最热、点击率最高、活跃度最高等等条件的top list、用户最近访问记录、粉丝列表等

9、redis的生产经验教训

 a、要进行master-slave主从同步配置,在出现服务故障时可以切换

 b、在master禁用数据持久化,只需要在slave上配置持久化

 c、物理内存+虚拟内存不足,这个时候dump一直死着,时间就了服务器挂掉,这个情况就是灾难。建议内存要64以上,SSD硬盘

 e、当redis物理内存使用超过内存总量的3/5时就会开始比较危险;就开始做swap,内存碎片大

 f、当达到最大内存时,会清空带有过期时间的key,即使key未到过期时间

 g、redis和DB同步写的问题,先写DB。后写redis,因为写内存基本上没问题 

##################################################################################
##################################################################################
##################################################################################

redis数据库部署

#更新yum 源
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo
yum install tree -y
grep keepcache /etc/yum.conf 
sed -i 's/keepcache=0/keepcache=1/g' /etc/yum.conf 
grep keepcache /etc/yum.conf 
#关闭selinux:
setenforce 0         #临时生效
sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config  #永久生效
setenforce 0    
sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config  
#关闭防火墙
/etc/init.d/iptables stop
chkconfig iptables off
chkconfig --list iptables
#时间同步
/usr/sbin/ntpdate pool.ntp.org
echo '#time sync by gao at 2010-2-1'>>/var/spool/cron/root
echo '*/10 * * * * /usr/sbin/ntpdate pool.ntp.org >/dev/null 2>&1'>>/var/spool/cron/root
crontab -l
#修改主机名
hostname MASTER
cp /etc/hosts /etc/hosts.bak
cp /etc/sysconfig/network /etc/sysconfig/network.bak
sed -i '10.0.0.3 MASTER' /etc/hosts 
sed -i '10.0.0.4 Slave' /etc/hosts 
sed -i -e '/HOSTNAME=/d' -e '1aHOSTNAME=MASTER' /etc/sysconfig/network
logout
############
hostname Slave
#cp /etc/hosts /etc/hosts.bak
cp /etc/sysconfig/network /etc/sysconfig/network.bak
sed -i '10.0.0.3 MASTER' /etc/hosts 
sed -i '10.0.0.4Slave' /etc/hosts 
sed -i -e '/HOSTNAME=/d' -e '1aHOSTNAME=Slave' /etc/sysconfig/network
logout
#########################################################################
#########################################################################

开始部署

redis部署环境

系统 centos 6.5
master:10.0.0.3
slave:10.0.0.4


开始部署

###################################

获取redis安装包

mkdir -p /home/lvnian/tools
cd /home/lvnian/tools/
rz -y redis-2.8.22.tar.gz
安装redis
mkdir -p /application/
tat xf redis-2.8.22.tar.gz
cd redis-2.8.22
#make MALLOC=jemalloc  #或者直接make也可以,这次是make安装,不加参数
make
make PREFIX=/application/redis-2.8.22 install
ln -s /application/redis-2.8.22/ /application/redis
ll /application/


上面步骤如果不出错,那就安装成功了会在/application/redis/bin/目录下生产5个可执行文件,分别是

redis-server  redis-cli  redis-benchmark  redis-check-aof  redis-check-dump   redis-sentinel  
=============================================
[root@MASTER ~]# ll /application/redis/bin/
total 15240
-rwxr-xr-x 1 root root 4586299 Nov 12 15:06 redis-benchmark
-rwxr-xr-x 1 root root   22185 Nov 12 15:06 redis-check-aof
-rwxr-xr-x 1 root root   45403 Nov 12 15:06 redis-check-dump
-rwxr-xr-x 1 root root 4688037 Nov 12 15:06 redis-cli
lrwxrwxrwx 1 root root      12 Nov 12 15:06 redis-sentinel -> redis-server
-rwxr-xr-x 1 root root 6254141 Nov 12 15:06 redis-server
[root@MASTER ~]# 
=================================================
redis-server  #redis服务器的daemon启动程序
redis-cli#redis 命令行操作工具,当然,你也可以用telnet根据其存文本协议操作
redis-benchmark#性能测试工具,测试redis在你的系统及你的配置文件
redis-check-aof#对更新日志appendonly.aof检查,是否可用,类似检查mysql binlog工具
redis-check-dump#用本地数据库rbd文件检查

 

###设置redis环境变量

echo " export PATH=/application/redis/bin/:$PATH" >>/etc/profile
tail -1 /etc/profile
. /etc/profile
which redis-server
===================
[root@M_Redis ~]# echo " export PATH=/application/redis/bin/:$PATH" >>/etc/profile
[root@M_Redis ~]# tail -1 /etc/profile
 export PATH=/application/redis/bin/:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
[root@M_Redis ~]# . /etc/profile
[root@M_Redis ~]# which redis-server
/application/redis/bin/redis-server
[root@M_Redis ~]# 
===================

###配置启动redis

cd /application/redis
mkdir -p /application/redis/conf
mkdir -p /application/redis/logs
pwd
cd /application/redis/conf
cp /home/lvnian/tools/redis-2.8.22/redis.conf /application/redis/conf
=====================
[root@M_Redis ~]# cd /application/redis
[root@M_Redis redis]# mkdir -p /application/redis/conf
[root@M_Redis redis]# mkdir -p /application/redis/logs
[root@M_Redis redis]# pwd
/application/redis
[root@M_Redis redis]# cd /application/redis/conf
[root@M_Redis conf]# cp /home/lvnian/tools/redis-2.8.22/redis.conf /application/redis/conf
[root@M_Redis conf]# ls
redis.conf
[root@M_Redis conf]# 
=====================


启动redis

redis-server /application/redis/conf/redis.conf &
netstat -lntup |grep redis
警告解决:
sysctl vm.overcommit_memory=1     
###不是必须操作,是运行内存不足时候,继续使用内存,防止数据丢掉的优化来的
echo "vm.overcommit_memory=1" >>/etc/sysctl.conf 
echo 1024 > /proc/sys/net/core/somaxconn
sysctl -p
lsof -i :6379
pkill redis 
redis-server /application/redis/conf/redis.conf &
netstat -lntup |grep redis
================================
[root@M_Redis conf]# redis-server /application/redis/conf/redis.conf &
[1] 4590
[root@M_Redis conf]# [4590] 04 Oct 13:13:19.040 * Increased maximum number of open files to 10032 (it was originally set to 1024).
                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 2.8.22 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                   
 (    '      ,       .-`  | `,    )     Running in stand alone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 4590
  `-._    `-._  `-./  _.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |           http://redis.io        
  `-._    `-._`-.__.-'_.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'                                               

[4590] 04 Oct 13:13:19.043 # Server started, Redis version 2.8.22
[4590] 04 Oct 13:13:19.044 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
[4590] 04 Oct 13:13:19.046 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
[4590] 04 Oct 13:13:19.046 * The server is now ready to accept connections on port 6379
[root@M_Redis conf]# netstat -lntup|grep redis
tcp        0      0 0.0.0.0:6379                0.0.0.0:*                   LISTEN      4590/redis-server * 
tcp        0      0 :::6379                     :::*                        LISTEN      4590/redis-server * 
[root@M_Redis conf]#
到这来就已经部署成功了,但是看上面的警告提示:
WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
 WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
我们操作下面命令就可以解决这个警告:
第一个警告的意思是:如果你的内存不够就执行上面提升的两个命令,也就是下面的内容,第二个警告就是提升我们要设置一个大于128的值
永久生效:
echo "vm.overcommit_memory=1" >>/etc/sysctl.conf 
echo "net.core.somaxconn = 512 " >>/etc/sysctl.conf 
或者临时生效:
sysctl vm.overcommit_memory=1      
echo 512 > /proc/sys/net/core/somaxconn
部署成功
vm.overcommit_memory 参数说明:
0:当用户空间请求更多的内存时,内核尝试估算剩余可用的内存
1:当设置为1的时候,内核允许超量使用内存知道用完为止,主要用于科学计算
2:当设置为2的时候,内核会使用一块决不过量使用的内存算法,即系统整个内存地址空间不能超过swap+50%的RAM值,50%的设置在overcommit_ratio中设置
##########################
redis 的启动和关闭命令:
启动
redis-server /application/redis/conf/redis.conf &
关闭:
redis-cli shutdown



redis测试:

[root@M_Redis conf]# redis-cli --help
redis-cli 2.8.22
Usage: redis-cli [OPTIONS] [cmd [arg [arg ...]]]
  -h <hostname>      Server hostname (default: 127.0.0.1).
  -p <port>          Server port (default: 6379).
  -s <socket>        Server socket (overrides hostname and port).
  -a <password>      Password to use when connecting to the server.
  -r <repeat>        Execute specified command N times.
  -i <interval>      When -r is used, waits <interval> seconds per command.
                     It is possible to specify sub-second times like -i 0.1.
  -n <db>            Database number.
  -x                 Read last argument from STDIN.
  -d <delimiter>     Multi-bulk delimiter in for raw formatting (default: \n).
  -c                 Enable cluster mode (follow -ASK and -MOVED redirections).
  --raw              Use raw formatting for replies (default when STDOUT is
                     not a tty).
  --no-raw           Force formatted output even when STDOUT is not a tty.
  --csv              Output in CSV format.
  --stat             Print rolling stats about server: mem, clients, ...
  --latency          Enter a special mode continuously sampling latency.
  --latency-history  Like --latency but tracking latency changes over time.
                     Default time interval is 15 sec. Change it using -i.
  --latency-dist     Shows latency as a spectrum, requires xterm 256 colors.
                     Default time interval is 1 sec. Change it using -i.
  --lru-test <keys>  Simulate a cache workload with an 80-20 distribution.
  --slave            Simulate a slave showing commands received from the master.
  --rdb <filename>   Transfer an RDB dump from remote server to local file.
  --pipe             Transfer raw Redis protocol from stdin to server.
  --pipe-timeout <n> In --pipe mode, abort with error if after sending all data.
                     no reply is received within <n> seconds.
                     Default timeout: 30. Use 0 to wait forever.
  --bigkeys          Sample Redis keys looking for big keys.
  --scan             List all keys using the SCAN command.
  --pattern <pat>    Useful with --scan to specify a SCAN pattern.
  --intrinsic-latency <sec> Run a test to measure intrinsic system latency.
                     The test will run for the specified amount of seconds.
  --eval <file>      Send an EVAL command using the Lua script at <file>.
  --help             Output this help and exit.
  --version          Output version and exit.
Examples:
  cat /etc/passwd | redis-cli -x set mypasswd
  redis-cli get mypasswd
  redis-cli -r 100 lpush mylist x
  redis-cli -r 100 -i 1 info | grep used_memory_human:
  redis-cli --eval myscript.lua key1 key2 , arg1 arg2 arg3
  redis-cli --scan --pattern '*:12345*'
  (Note: when using --eval the comma separates KEYS[] from ARGV[] items)
When no command is given, redis-cli starts in interactive mode.
Type "help" in interactive mode for information on available commands.
[root@M_Redis conf]# 
##############################################################

可以直接resis-cli 进入redis客户端


[root@M_Redis conf]# redis-cli 
127.0.0.1:6379> 
127.0.0.1:6379>

按tab键看帮助,或者help +tab见查看帮助


 

redis客户端里面设置key-values

客户端里面交互式设置

127.0.0.1:6379> set key01 lvnian01                 ##设置key-value
OK
127.0.0.1:6379> get key01                          ##获取key的value
"lvnian01"
127.0.0.1:6379> 
127.0.0.1:6379> del key01                          ##删除key  
(integer) 1
127.0.0.1:6379> get key01
(nil)
127.0.0.1:6379>  set key01 lvnian01  
127.0.0.1:6379>  set key02 lvnian02  
127.0.0.1:6379> keys *
 1) "key01"
 2) "key02"
##############################################################

linux命令行不交互设置方法

[root@M_Redis conf]# redis-cli -h 10.0.0.3 -p 6379 set key01 lvnian01
OK
[root@M_Redis conf]# redis-cli -h 10.0.0.3 -p 6379 set key02 lvnian02
OK
[root@M_Redis conf]# redis-cli -h 10.0.0.3 -p 6379 get key02    
"lvnian02"
[root@M_Redis conf]# redis-cli -h 10.0.0.3 -p 6379 get key01
"lvnian01"
[root@M_Redis conf]# redis-cli -h 10.0.0.3 -p 6379 get lvnian01        #不能通过value去key
(nil)
[root@M_Redis conf]# 
################批量插入数据
[root@M_Redis conf]# for n in `seq 10` ;do redis-cli -h 10.0.0.3 -p 6379 set key$n lvnian$n ;done     
OK
OK
OK
OK
OK
OK
OK
OK
OK
OK
[root@M_Redis conf]# for n in `seq 10` ;do redis-cli -h 10.0.0.3 -p 6379 get key$n ;done         
"lvnian1"
"lvnian2"
"lvnian3"
"lvnian4"
"lvnian5"
"lvnian6"
"lvnian7"
"lvnian8"
"lvnian9"
"lvnian10"
[root@M_Redis conf]# 
##############################################################

telnet 方式设置key-value

[root@M_Redis conf]# telnet 10.0.0.3 6379 
Trying 10.0.0.3...
Connected to 10.0.0.3.
Escape character is '^]'.
set key001 lvnian001
+OK
get key001
$9
lvnian001
set key002 lvnian002
+OK
del key001
:1
get key001
$-1
get key002
$9
lvnian002
get key002
$9
lvnian002
del key002
:1
get key002
$-1
##########################################################################
##########################################################################
##########################################################################

###redis 字符串类型

10.0.0.3:6379> set mystr "my name is lvnian"
OK
10.0.0.3:6379> get mystr
"my name is lvnian"
10.0.0.3:6379>


###redis基本类型自增

10.0.0.3:6379> set counter 100
OK
10.0.0.3:6379> incr counter
(integer) 101
10.0.0.3:6379> incr counter
(integer) 102
10.0.0.3:6379> incr counter
(integer) 103
10.0.0.3:6379>
10.0.0.3:6379> get counter
"103"
10.0.0.3:6379>

###列表类型  

   ##rpush 是设置,rlange 是查看
[root@M_Redis conf]# redis-cli rpush messages "hello lvnian" 
(integer) 1
[root@M_Redis conf]# 
[root@M_Redis conf]# [6127] 04 Oct 14:08:09.082 * 1 changes in 900 seconds. Saving...
[6127] 04 Oct 14:08:09.083 * Background saving started by pid 6281
[6281] 04 Oct 14:08:09.093 * DB saved on disk
[6281] 04 Oct 14:08:09.094 * RDB: 0 MB of memory used by copy-on-write
[6127] 04 Oct 14:08:09.183 * Background saving terminated with success
                                  #######上面这些,是在执行过程中跳出来的,是redis定期往磁盘写数据的内容
[root@M_Redis conf]# redis-cli rpush messages "hello lvnian ! "
(integer) 2
[root@M_Redis conf]# redis-cli rpush messages "hello xiaowang ! "      
(integer) 3
[root@M_Redis conf]# redis-cli rpush messages "hello xiaozhang ! "    
(integer) 4
[root@M_Redis conf]# redis-cli lrange messages 0 3
1) "hello lvnian"
2) "hello lvnian ! "
3) "hello xiaowang ! "
4) "hello xiaozhang ! "
[root@M_Redis conf]# redis-cli lrange messages 0 2
1) "hello lvnian"
2) "hello lvnian ! "
3) "hello xiaowang ! "
[root@M_Redis conf]#

 


###redis 集合功能

127.0.0.1:6379> help sadd
  SADD key member [member ...]
  summary: Add one or more members to a set
  since: 1.0.0
  group: set
127.0.0.1:6379> sadd myset a
(integer) 1
127.0.0.1:6379> sadd myset b
(integer) 1
127.0.0.1:6379> sadd myset c
(integer) 1
127.0.0.1:6379> sadd myset d
(integer) 1
127.0.0.1:6379> sadd myset e
(integer) 1
127.0.0.1:6379> smembers myset
1) "b"
2) "c"
3) "d"
4) "a"
5) "e"
127.0.0.1:6379>