redis简介和使用

简介

redis(Remote Dictionary Server)是一种Nosql技术,它是一个开源的高级kv存储和数据结构存储系统,它经常被拿来和Memcached相比较,但是Memcached不提供持久化的数据保存机制而redis可以将数据保存在磁盘中,redis不仅仅是能够存储key和value这种简单的键值对,还能存储例如集合、hash表、列表、字典等。redis在整个运行过程中,数据统统都是存储在内存中的,因此,性能是相当高的,由于此特性,redis对于内存的要求比较高,它会周期性的将内存中的数据写入在磁盘中,从而实现数据持久化的访问能力,但是这种存储只是保证redis在下次启动还有数据可以读取,而不是提供访问。redis是单线程服务的,只有一个线程。redis还支持主从模式以及支持通过lua脚本去编写扩展,并且支持高可用和分布式集群解决方案。

1

Redis特点

  1. 运行在内存
  2. 持久化
  3. 主从(借助于sentinel实现一定意义上的HA)
  4. Clustering(分布式存储)
  5. 数据机构服务器:支持存储string、list、hash、set、Sorted Set,Bitmap,HyperLoglogs
  6. 能够作为队列使用

备注:redis是单线程,但是这并不意味着会成为运行时的瓶颈,每秒能够支撑50W的并发

哪些公司在使用

  • Twitter
  • pinterest
  • tumblr
  • github
  • stack overflow
  • digg
  • blizard
  • flickr
  • weibo

数据库存储系统分类

常见的数据库系统有以下几类:

  1. RDBMS:Oracle、DB2、Mysql
  2. NoSQL:MongoDB、Redis、HBase、Memcached
  3. NewSQL:Aerospike、FounddtionDB、RethinkDB

而NoSQL又分为以下几类:

  1. Key-Value NoSql:Memcached、Redis
  2. Column family NoSQL:Cassandra、HBase
  3. Documentation NoSQL:MongoDB
  4. Graph NoSQL:Neo4j

Redis 3.0

  • 2015年4月1日正式推出,它的特性:
  • redis cluster
  • 新的”embedded string”
  • LRU演算法的改进:预设随机取5个样本,插入并排序至一个pool。移除最佳者,如此反复,直到内存用量小于maxmemory的设定。

Redis的组件

最早只有1W行代码,网址是[http://www.redis.io][2],它的组件有:

  1. redis-server
  2. redis-cli
  3. redis-benchmark(压测工具)
  4. redis-check-dump && redis-check-aof 能够去检测文件是否损坏两种格式RDB/AOF格式

redis的安装

redis的安装是非常简单的,你甚至都不需要去configure,直接make && makeinstall make也不需要带过多的参数。

官网:

3

  1. 编译

    wget -c http://download.redis.io/releases/redis-3.0.6.tar.gz 
    tar xvf redis-version.tar.gz
    cd redis-version
    make && make install
> 注意:安装需要编译环境,例如gcc等必要工具的支持

2.提示缺少tcl,可以通过yum install tcl去安装

[root@redis redis-3.0.6]# make test
cd src && make test
make[1]: Entering directory `/root/redis-3.0.6/src'
You need tcl 8.5 or newer in order to run the Redis test
make[1]: *** [test] Error 1
make[1]: Leaving directory `/root/redis-3.0.6/src'
make: *** [test] Error 2

3.解决错误之后,我们就可以通过redis-server redis.conf去启动redis服务端了

[root@redis redis-3.0.6]# redis-server redis.conf 
4624:M 20 Dec 11:56:53.375 * Increased maximum number of open files to 10032 (it was originally set to 1024).
                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 3.0.6 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                   
 (    '      ,       .-`  | `,    )     Running in standalone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 4624
  `-._    `-._  `-./  _.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |           http://redis.io        
  `-._    `-._`-.__.-'_.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'                                               

4624:M 20 Dec 11:56:53.376 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
4624:M 20 Dec 11:56:53.376 # Server started, Redis version 3.0.6
4624:M 20 Dec 11:56:53.376 # 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.
4624:M 20 Dec 11:56:53.376 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
4624:M 20 Dec 11:56:53.376 * The server is now ready to accept connections on port 6379

从上面的输出信息中,我们看到redis是运行在TCP的6379端口上的。

注意:默认的redis.conf文件的daemonize参数为no,所以redis不会在后台运行,这时要测试,我们需要重新开一个终端。修改为yes则为>后台运行redis。另外配置文件中规定了pid文件,log文件和数据文件的地址,如果有需要先修改,默认log信息定向到stdout

4.redis的配置文件

redis.conf的主要配置参数的含义:

  • daemonize:是否以后台daemon方式运行,no为禁止,yes为运行

  • pidfile:pid文件位置

  • tcp-backlog(如果访问量非常大,接收缓冲已经满了,制定一个位置缓冲新请求,tcp协议一般会有backlog)

  • bind 监听地址,默认在127.0.0.1 我们可以指定多个地址,例如bind 127.0.0.1 10.0.1.243

  • port:监听的端口号,默认是6379,可以自己指定其他地址

  • unixsocket和unixsocketperm 定义sokcet的pid文件位置和权限如果你的服务器和redis在同一台服务器上推荐指定socket方式,给予socket的方式在内存中直接交换而不经过tcp协议栈去封装,

  • timeout:请求超时时间,0表示禁用

  • loglevel:log信息级别

  • logfile:log文件位置

  • databases:开启数据库的数量,在redis的集群中只支持0库

  • save * :保存快照的频率,第一个表示多长时间,第三个*表示执行多少次写操作。在一定时间内执行一定数量的写操作时,自动保存快照。可设置多个条件,例如以下,表示900秒有1个键发生变化就执行写操作,如果在300秒内,有10个键发生变化就执行写操作,如果60秒有1000个键发生变化则执行写操作。

    save 900 1
    save 300 10
    save 60 10000
  • rdbcompression:是否使用压缩

  • dbfilename:数据快照文件名(只是文件名,不包括目录)

  • dir:数据快照的保存目录(这个是目录)

  • appendonly:是否开启appendonlylog,开启的话每次写操作会记一条log,这会提高数据抗风险能力,但影响效率。

  • appendfsync:appendonlylog如何同步到磁盘(三个选项,分别是每次写都强制调用fsync、每秒启用一次fsync、不调用fsync等待系统自己同步)

  • slaveof, 启动主从,需要指定iP和端口

使用redis客户端

1.我们修改redis的配置文件,将daemonize修改为yes,将bind打开,然后保存,执行如下操作

[root@redis redis-3.0.6]# redis-server /etc/redis.conf 
[root@redis redis-3.0.6]# redis-cli 
127.0.0.1:6379> 

注意:默认redis-cli没有开启认证机制,所以直接redis-cli就可以进入redis命令行界面

2.redis的帮助系统,我们进入cli后,可以输入help查看帮助信息

127.0.0.1:6379> help
redis-cli 3.0.6
Type: "help @<group>" to get a list of commands in <group>
      "help <command>" for help on <command>
      "help <tab>" to get a list of possible help topics
      "quit" to exit

例如我们要查看String的相关参数可以使用help @String

127.0.0.1:6379> help @String

  APPEND key value
  summary: Append a value to a key
  since: 2.0.0

  BITCOUNT key [start end]
  summary: Count set bits in a string
  since: 2.6.0
  ……

我们也可以使用help [tab]去tab一些选项

redis的常用命令

Strings的命

1.打开数据库(名称空间):SELE [num],最多打开16个

127.0.0.1:6379> SELECT 1
OK
127.0.0.1:6379[1]> SELECT 2
OK

2.设置字符串

127.0.0.1:6379> help set

  SET key value [EX seconds] [PX milliseconds] [NX|XX]
  summary: Set the string value of a key
  since: 1.0.0
  group: string

3.设置key和value

127.0.0.1:6379> SET disto fedora
OK
127.0.0.1:6379> GET disto
"fedora"

4.键值在同一名称空间中必须唯一

127.0.0.1:6379> SET disto fedora
OK
127.0.0.1:6379> GET disto
"fedora"
127.0.0.1:6379> SET disto ubuntu 
OK
127.0.0.1:6379> GET disto
"ubuntu"
127.0.0.1:6379> 

5.设置自动增长的值

127.0.0.1:6379> SET count 0
OK
127.0.0.1:6379> INCR count
(integer) 1
127.0.0.1:6379> INCR count
(integer) 2
127.0.0.1:6379> INCR count
(integer) 3

6.设置自动减的值

127.0.0.1:6379> DECR count
(integer) 2
127.0.0.1:6379> DECR count
(integer) 1
127.0.0.1:6379> DECR count
(integer) 0
127.0.0.1:6379> DECR count
(integer) -1
127.0.0.1:6379> DECR count
(integer) -2

7.设置键的手动过期或自动过期时间

SET key value [EX seconds] [PX milliseconds] [NX|XX]

EX 过期时间 NX 如果一个键不存在才创建

127.0.0.1:6379> SET disto gento NX
(nil)

XX表示存在才创建

127.0.0.1:6379> SET foo bar XX
(nil)

8.set还支持integer,但是必须为整数

1)设置integer

127.0.0.1:6379> set foo 1
OK
127.0.0.1:6379> get foo
"1"

2)非integer会出现错误

127.0.0.1:6379> set foo bar
OK
127.0.0.1:6379> incr foo
(error) ERR value is not an integer or out of range

List的常用命令

1.获取list的帮助

127.0.0.1:6379> help @list

  BLPOP key [key ...] timeout
  summary: Remove and get the first element in a list, or block until one is available
  since: 2.0.0

  BRPOP key [key ...] timeout
  summary: Remove and get the last element in a list, or block until one is available
  since: 2.0.0

  BRPOPLPUSH source destination timeout
  summary: Pop a value from a list, push it to another list and return it; or block until one is available
  since: 2.2.0

2.定义一个list

127.0.0.1:6379> LPUSH l1 mon
(integer) 1

3.获取list的值

127.0.0.1:6379> LINDEX l1 0
"mon"
127.0.0.1:6379>

比如我们在给l1增加一个值

127.0.0.1:6379> LPUSH l1 sun
(integer) 2

那么,此时,我们通过LINDEX l1 0获取的就是新增加的sun,而LINDEX l1 1则是mon

127.0.0.1:6379> LINDEX l1 0
"sun"
127.0.0.1:6379> LINDEX l1 1
"mon"

那么,我们要想从右侧增加一个值呢?我们可以使用RPUSH去创建

127.0.0.1:6379> RPUSH l1 tue
(integer) 3
127.0.0.1:6379> LINDEX l1 2
"tue"

修改一个值

127.0.0.1:6379> LSET l1 1 fri
OK
127.0.0.1:6379> LINDEX l1 1
"fri"

要想从左侧弹出一个值用LPOP,要想从右侧则用RPOP

127.0.0.1:6379> RPOP l1
"tue"
127.0.0.1:6379> RPOP l1
"fri"

无序集合的操作

1.创建一个集合

127.0.0.1:6379> SADD w1 mon tue wed thu fre sat sun
(integer) 7
127.0.0.1:6379> SADD w2 tue thu day
(integer) 3

2.求交集

127.0.0.1:6379> SINTER w1 w2
1) "thu"
2) "tue"
127.0.0.1:6379> 

2.求并集

127.0.0.1:6379> SUNION w1 w2
1) "thu"
2) "day"
3) "sun"
4) "tue"
5) "fre"
6) "wed"
7) "mon"
8) "sat"
127.0.0.1:6379> 

3.弹出元素

127.0.0.1:6379> SPOP w1
"sun"

5.查看元素是否存在

127.0.0.1:6379> SISMEMBER w1 mon
(integer) 1
127.0.0.1:6379> SISMEMBER w1 fri
(integer) 0

有序集合操作

127.0.0.1:6379> HELP @SORTED_SET

1.添加元素到集合

127.0.0.1:6379> ZADD weekday1 1 mon 2 tue 3 wed 
(integer) 3

2.获取元素的总数

127.0.0.1:6379> ZCARD weekday1
(integer) 3

3.查看索引号

127.0.0.1:6379> ZRANK weekday1 tue
(integer) 1

4.根据元素获取SCORE

127.0.0.1:6379> ZSCORE weekday1 mon
"1"

5.指明索引范围获取值

127.0.0.1:6379> ZRANGE weekday1 0 2
1) "mon"
2) "tue"
3) "wed"

Hashes的操作

1.添加/补充新值一个hashes

127.0.0.1:6379> HSET h1 a mon
(integer) 1

2.获取值

127.0.0.1:6379> HGET h1 a
"mon"

3.获取所有值

127.0.0.1:6379> HKEYS h1
1) "a"
2) "b"

4.获取元素总数

127.0.0.1:6379> HLEN h1
(integer) 2

5.删除键

127.0.0.1:6379> HDEL h1 a
(integer) 1
127.0.0.1:6379> HGET h1 a
(nil)