并发访问控制是多线程开发的难点问题,
Redis 为了避免采用多线程需要引入同步原语来保护共享资源的并发访问,直接使用了单线程模式。
Redis 快的主要原因:
1. Redis使用了很多高效的数据结构
压缩列表:类似于数组,数组中的每一个元素对应保存一个数据。
压缩列表在表头保存三个字段表示列表长度,列表尾部偏移量,entry个数,压缩列表尾部还有一个结束标志。
2. 因为Redis也使用了多路复用的IO模型。
在一次请求过程中操作包含:
bind/listen
accept ★
recv
parse
get
send
潜在的阻塞点有两个:accept(监听到请求但是未能成功建立连接) 和 recev(通过客户端读取数据,但是数据一直没有到达)
accept:监听套接字设置非阻塞模式。虽然Redis不需要继续等待,但是需要一个机制监听套接字等待后续请求,并在有请求时通知Redis。
recev:Redis在调用recv 后,如果已连接的的套接字一直没有数据到达,Redis 可以返回处理其他操作。当然也需要一个机制监听并在合适时候通知Redis.
这个机制就是Linux的IO多路复用机制。一个线程处理多个IO流,select/epoll机制。
该机制允许内核中同时存在多个监听套接字和已连接的套接字。
操作系统对网络连接的过程解析:
Redis操作过程的其他注意点
单线程的潜在性能瓶颈
1,bigkey 操作
字符串类型的单个value值很大;或者是哈希,列表,集合,有序集合的元素个数过多,下面的命令可以看bigkey。
redis-cli -h -a --bigkeys
2,潜在的大数据量操作
key * ,get all
3,大量的客户端接入
4,范围操作
5,往redis 写入大量数据后导致哈希冲突和rehash带来的阻塞问题
全局哈希表保存的是指向具体值的指针
Redis 通过链式哈希的方式解决哈希冲突,同一个哈希桶中的多个元素用一个链表来保存,他们之间依次用指针连接。
当冲突很多,或者哈希表容量不足时,会使用 渐进式rehash ,一次带走当前索引位置的entries ,分多次完成数据转移。