Redis之初探

Redis是什么

  • Redis是一个开源,内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理。
  • Key-Value格式的缓存和存储服务器;
  • 数据结构服务器,它支持字符串、哈希表、列表、集合、有序集合,位图,hyperloglogs等数据类型;
  • 所有数据集必须在内存中使用,磁盘是用来持久数据的。
  • 是一种NoSQL数据库

Redis和Memcached的比较

  • 性能和用途:Memcached优先考虑高性能和特殊响应时间,适用于简单缓存任务;Redis提供相当的性能,支持更高级的使用案例,包括异步和非阻塞I/O操作。
  • 数据结构和功能:Redis支持更丰富的数据操作,而Memcached只是单一key-value内存Cache。
  • 可靠性和持久化:Redis对可靠性要求较高,支持数据持久化,而Memcached只是内存缓存,对可靠性无要求。
  • 集群模式:Redis原生支持集群模式,而Memcached需要依靠客户端来实现集群。
  • 性能对比:Redis在存储小数据时比Memcached性能更高,但在大数据中稍有逊色。

Redis数据持久化

Redis的数据全部在内存中,如果突然宕机,数据就会全部丢失,因此必须有一种机制来保证redis的数据在发生突发状况时不会丢失、或者只丢失少量,于是必须根据一些策略来把redis内存中的数据写到磁盘中,这样当redis服务重启时,就会将硬盘中的数据恢复到内存中。Redis持久化的意义就是为了保证突然宕机,内存数据不会全部丢失。

redis有两种持久化机制
RDB和AOF。Redis4.0后支持RDB和AOF两种持久化机制混合使用,所以存在三种持久化策略。

  • RDB是基于快照一次的全量备份,即周期性的把redis当前内存中的全量数据写入到一个快照文件中(周期时间可以通过配置来调整)。
  • AOF(Append-only file)日志存储的是redis服务器的顺序指令序列,即对内存中数据进行修改的指令记录。当redis收到客户端修改指令后,先进行参数校验,如果校验通过,先把该指令存储到AOF日志文件中,也就是先存到磁盘,然后再执行该修改指令。

Redis是单线程还是多线程?

  • Redis5及之前是单线程版本

Redis5及之前的版本使用的是单线程,也就是说只有一个 worker队列,所有的读写操作都要在这一个队列进行操作,好处是不会有线程安全问题(因为它在读写时就只有一个线程,那对于读写操作肯定没有线程安全问题啊!),但是读写 write、read 这些系统调用在Redis执行期间占用了大部分的 CPU 时间,所以这就是单线程模式的缺点。
所以也就在Redis6引入了多线程版本,接着往下看。

  • Redis6开始引入多线程版本(实际上是 单线程+多线程 版本)

Redis6引入了多线程机制,但是不是说有多个worker线程同时并发读写, 而是它有 “一个 worker线程+多个IO子线程”,其实就是在 IO 就绪之后使用多线程提升读写解析数据的效率,而在 操作内存数据的时候还是用单线程。
利用这种单线程+多线程共同运作的机制,将CPU的性能显著提升了。
同时,这种机制同样不会产生线程安全问题,因为Redis在针对数据的内存操作时,是在一个公共的worker队列中实现的,先进先出,所以不会有线程安全问题。
Redis6之所以保留worker单主线程是因为单线程机制使得Redis内部实现的复杂度大大降低,而且可以保证操作的线程安全。(如果整个过程全让子线程做了,整个任务处理过程太重,就失去了原来单线程高效处理的优势了)
简单来说,就是 “请求是多线程的,但核心的内存读写操作(或者说读写计算)仍然是单线程的”。

Redis 为什么单线程还这么快?

误区1:高性能的服务器一定是多线程的!
误区2:多线程(CPU上下文会切换!)一定比单线程效率高!

  • redis是将所有的数据全部放在内存中的,所以说使用单线程去操作效率就是最高的,多线程(CPU上下文会切换,耗时的操作!!!)。
  • 对于内存系统来说,如果没有上下文切换效率就是最高的!多次读写都是在一个CPU上的,在内存情况下,这个就是最佳的方案!
  • 一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。多线程会进行CPU上下文会切换,造成时间消耗。

安装部署

https://redis.io/
https://www.redis.net.cn/

因为Redis是C实现的,因此需要安装如下依赖,其次,有可能需要安装python3。

# yum install cpp
# yum install binutils
# yum install glibc
# yum install glibc-kernheaders
# yum install glibc-common
# yum install glibc-devel
# yum install gcc
# yum install make

# tar -zxvf  redis-7.0.15.tar.gz
# cd redis-7.0.15
# make && make install

Hint: It's a good idea to run 'make test' ;)

make[1]: 离开目录“/data/apps/redis-7.0.15/src”
cd src && make install
make[1]: 进入目录“/data/apps/redis-7.0.15/src”
    CC Makefile.dep
make[1]: 离开目录“/data/apps/redis-7.0.15/src”
make[1]: 进入目录“/data/apps/redis-7.0.15/src”

Hint: It's a good idea to run 'make test' ;)

    INSTALL redis-server
    INSTALL redis-benchmark
    INSTALL redis-cli
make[1]: 离开目录“/data/apps/redis-7.0.15/src”
  • redis的默认安装路径:/usr/local/bin
[root@jgswy-pro bin]# ll
总用量 21556
-rwxr-xr-x. 1 root root  5205488 5月  28 21:03 redis-benchmark
lrwxrwxrwx. 1 root root       12 5月  28 21:03 redis-check-aof -> redis-server
lrwxrwxrwx. 1 root root       12 5月  28 21:03 redis-check-rdb -> redis-server
-rwxr-xr-x. 1 root root  5422896 5月  28 21:03 redis-cli
lrwxrwxrwx. 1 root root       12 5月  28 21:03 redis-sentinel -> redis-server
-rwxr-xr-x. 1 root root 11441032 5月  28 21:03 redis-server
  • redis默认不是后台启动,需要修改配置文件可以后台启动。
# cp /data/apps/redis-7.0.15/redis.conf  /data/apps/redis-7.0.15/redis.conf.bak
# vi /data/apps/redis-7.0.15/redis.conf
daemonize yes  #守护进程,修改为yes后即可后台运行
requirepass 123321  #密码,设置后访问Redis必须输人密码

# redis-server /data/apps/redis-7.0.15/redis.conf

# ss -tul
Netid State      Recv-Q Send-Q                     Local Address:Port                                      Peer Address:Port
udp   UNCONN     0      0                              127.0.0.1:323                                                  *:*
udp   UNCONN     0      0                                  [::1]:323                                               [::]:*
tcp   LISTEN     0      128                                    *:ssh                                                  *:*
tcp   LISTEN     0      100                            127.0.0.1:smtp                                                 *:*
tcp   LISTEN     0      128                            127.0.0.1:6379                                                 *:*
tcp   LISTEN     0      128                                 [::]:ssh                                               [::]:*
tcp   LISTEN     0      128                                 [::]:hbci                                              [::]:*
tcp   LISTEN     0      100                                [::1]:smtp                                              [::]:*
tcp   LISTEN     0      128                                 [::]:9115                                              [::]:*
tcp   LISTEN     0      128                                 [::]:websm                                             [::]:*
tcp   LISTEN     0      128                                [::1]:6379                                              [::]:*
tcp   LISTEN     0      128                                 [::]:jetdirect                                         [::]:*
[root@jgswy-pro ~]#

配置文件
1、网络配置

2、通用配置

3、快照
持久化,在规定的时间内,执行了多少次操作,则会持久化到文件.rdb.aof
redis 是内存数据库,如果没有持久化,那么数据断电及失!

4、安全
配置redis密码

# redis-cli -p 6379
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> CONFIG GET requirepass
1) "requirepass"
2) ""
127.0.0.1:6379> CONFIG SET requirepass "P@ssw0rd"
OK
127.0.0.1:6379> CONFIG GET requirepass                      #获取密码
1) "requirepass"
2) "P@ssw0rd"

127.0.0.1:6379> ping                                        
(error) NOAUTH Authentication required.
127.0.0.1:6379> AUTH P@ssw0rd                               #输入密码
OK
127.0.0.1:6379> ping
PONG

5、限制客户端

6、aof配置

常用命令

  • 测试登录库
# redis-cli -p 6379
127.0.0.1:6379> set name test
OK
127.0.0.1:6379> get name
"test"
127.0.0.1:6379>
  • redis默认有16个库(0-15),默认使用的是0,可以用select进行切换。每个数据库互相隔离。
# redis-cli -p 6379
127.0.0.1:6379> SELECT 6       #切换到数据库6
OK
127.0.0.1:6379[6]> DBSIZE      #查看数据库大小
(integer) 0

127.0.0.1:6379[6]> KEYS *      #查看数据库所有的key
(empty array)

127.0.0.1:6379[6]> flushdb     #清空当前库的内容
OK
127.0.0.1:6379[6]> select 0
OK

127.0.0.1:6379> KEYS *
1) "myhash"
2) "mylist"
3) "name"
4) "key:__rand_int__"
5) "counter:__rand_int__"
127.0.0.1:6379> select 2
OK
127.0.0.1:6379[2]> flushall    #清空所有库的内容
OK
127.0.0.1:6379[2]> select 0
OK
127.0.0.1:6379> keys *
(empty array)

# redis-cli -p 6379
127.0.0.1:6379> SET name xiaoming
OK
127.0.0.1:6379> KEYS *
1) "name"
127.0.0.1:6379> SET age 1                  #插入数据
OK
127.0.0.1:6379> KEYS *
1) "name"
2) "age"
127.0.0.1:6379> EXISTS name                #判断name是否存在,存在返回1,不存在返回0
(integer) 1
127.0.0.1:6379> EXISTS name1
(integer) 0
127.0.0.1:6379> move name 1                #将name从当前库移动到库1
(integer) 1

127.0.0.1:6379> set name xioaming
OK
127.0.0.1:6379> get name
"xioaming"
127.0.0.1:6379> expire name 10             #设置key的过期时间10秒,倒计时10秒后数据过期
(integer) 1
127.0.0.1:6379> ttl name                   #查看当前key的时间
(integer) 2
127.0.0.1:6379> ttl name
(integer) -2
127.0.0.1:6379> get name
(nil)

127.0.0.1:6379> set name xiaoming
OK
127.0.0.1:6379> type name                  #查看当前key的数据类型
string

并发测试

redis提供了一款测试工具redis-benchmark

redis-benchmark 参数
-h:指定主机名
-p:指定端口,默认6379
-c:指定并发连接数
-n:指定请求数
-d:以字节形式指定SET/GET值的数据大小

测试100个并发连接,每个并发100000个请求

# redis-benchmark -h localhost -p 6379 -c 100 -n 100000
====== PING_INLINE ======
  100000 requests completed in 1.36 seconds                          #100000个请求
  100 parallel clients                                               #100个并行客户端
  3 bytes payload                                                    #每次写入3个字节
  keep alive: 1                                                      #一个服务器处理请求
  host configuration "save": 3600 1 300 100 60 10000
  host configuration "appendonly": no
  multi-thread: no

Latency by percentile distribution:
0.000% <= 0.247 milliseconds (cumulative count 2)
50.000% <= 0.663 milliseconds (cumulative count 53433)
75.000% <= 0.687 milliseconds (cumulative count 78832)
87.500% <= 0.711 milliseconds (cumulative count 88427)
93.750% <= 1.015 milliseconds (cumulative count 93767)
96.875% <= 1.423 milliseconds (cumulative count 96926)
98.438% <= 1.623 milliseconds (cumulative count 98501)
99.219% <= 1.719 milliseconds (cumulative count 99234)
99.609% <= 1.783 milliseconds (cumulative count 99621)
99.805% <= 2.095 milliseconds (cumulative count 99805)
99.902% <= 2.599 milliseconds (cumulative count 99903)
99.951% <= 2.951 milliseconds (cumulative count 99952)
99.976% <= 3.135 milliseconds (cumulative count 99976)
99.988% <= 3.303 milliseconds (cumulative count 99988)
99.994% <= 3.391 milliseconds (cumulative count 99994)
99.997% <= 3.439 milliseconds (cumulative count 99997)
99.998% <= 3.479 milliseconds (cumulative count 99999)
99.999% <= 3.495 milliseconds (cumulative count 100000)
100.000% <= 3.495 milliseconds (cumulative count 100000)            #所有请求在3.495毫秒完成

Summary:
  throughput summary: 73367.57 requests per second                  #每秒处理73367.57个请求
  latency summary (msec):
          avg       min       p50       p95       p99       max
        0.716     0.240     0.663     1.175     1.695     3.495

...

====== SET ======
  100000 requests completed in 1.33 seconds
  100 parallel clients
  3 bytes payload
  keep alive: 1
  host configuration "save": 3600 1 300 100 60 10000
  host configuration "appendonly": no
  multi-thread: no

Latency by percentile distribution:
0.000% <= 0.303 milliseconds (cumulative count 3)
50.000% <= 0.671 milliseconds (cumulative count 57052)
75.000% <= 0.687 milliseconds (cumulative count 77451)
87.500% <= 0.703 milliseconds (cumulative count 92613)
93.750% <= 0.711 milliseconds (cumulative count 95469)
96.875% <= 0.719 milliseconds (cumulative count 97002)
98.438% <= 0.735 milliseconds (cumulative count 98636)
99.219% <= 0.767 milliseconds (cumulative count 99254)
99.609% <= 0.855 milliseconds (cumulative count 99635)
99.805% <= 1.023 milliseconds (cumulative count 99808)
99.902% <= 1.871 milliseconds (cumulative count 99903)
99.951% <= 2.175 milliseconds (cumulative count 99952)
99.976% <= 2.351 milliseconds (cumulative count 99976)
99.988% <= 2.479 milliseconds (cumulative count 99988)
99.994% <= 2.551 milliseconds (cumulative count 99994)
99.997% <= 2.583 milliseconds (cumulative count 99997)
99.998% <= 2.607 milliseconds (cumulative count 99999)
99.999% <= 2.623 milliseconds (cumulative count 100000)
100.000% <= 2.623 milliseconds (cumulative count 100000)

Cumulative distribution of latencies:
0.000% <= 0.103 milliseconds (cumulative count 0)
0.003% <= 0.303 milliseconds (cumulative count 3)
0.030% <= 0.407 milliseconds (cumulative count 30)
0.067% <= 0.503 milliseconds (cumulative count 67)
0.257% <= 0.607 milliseconds (cumulative count 257)
92.613% <= 0.703 milliseconds (cumulative count 92613)
99.412% <= 0.807 milliseconds (cumulative count 99412)
99.722% <= 0.903 milliseconds (cumulative count 99722)
99.794% <= 1.007 milliseconds (cumulative count 99794)
99.833% <= 1.103 milliseconds (cumulative count 99833)
99.850% <= 1.207 milliseconds (cumulative count 99850)
99.860% <= 1.303 milliseconds (cumulative count 99860)
99.866% <= 1.407 milliseconds (cumulative count 99866)
99.870% <= 1.503 milliseconds (cumulative count 99870)
99.874% <= 1.607 milliseconds (cumulative count 99874)
99.880% <= 1.703 milliseconds (cumulative count 99880)
99.893% <= 1.807 milliseconds (cumulative count 99893)
99.910% <= 1.903 milliseconds (cumulative count 99910)
99.928% <= 2.007 milliseconds (cumulative count 99928)
99.941% <= 2.103 milliseconds (cumulative count 99941)
100.000% <= 3.103 milliseconds (cumulative count 100000)

Summary:
  throughput summary: 75075.07 requests per second                  #每秒处理75075个请求
  latency summary (msec):
          avg       min       p50       p95       p99       max
        0.673     0.296     0.671     0.711     0.751     2.623

...

参考

https://blog.csdn.net/Awwwze/article/details/115396745
https://blog.csdn.net/Wong_H/article/details/126196774
https://blog.csdn.net/Awwwze/article/details/115396745

posted @ 2024-05-29 15:18  *一炁化三清*  阅读(8)  评论(0编辑  收藏  举报