功能:存储数据。数据与apiserver保持一致,实时更新。因此除了直接调用apiserver进行读请求,还可以直接通过indexer读取,减轻apiserver的压力。
原理:数据主要通过threadSafeMap来存放 (满足ThreadSafeStore接口)
可以通过NewIndexer函数创建(实际返回的是cache)
代码:
func NewIndexer(keyFunc KeyFunc, indexers Indexers) Indexer {
return &cache{
cacheStorage: NewThreadSafeStore(indexers, Indices{}),
keyFunc: keyFunc,
}
}
cache中的所有存储操作,调用的都是cacheStorage的方法
为什么要使用Index: 在指定namespace或者其他条件进行检索时,需要用到index来加速检索。否则使用List或者Get,效率很低
在cache中,存在多个Index相关的方法,那么什么是index呢
首先需要介绍三个数据类型: index/indicies/indexer
// Index maps the indexed value to a set of keys in the store that match on that value
//key是IndexFunc计算出来的结果,⽐如default,value是所有obj的key的集合
type Index map[string]sets.String
// 这里sets.String 其实是一个value为空struct的map,所以可以作为Set使用
// Indexers maps a name to an IndexFunc
//key是索引的分类名,⽐如namespace,value是⼀个⽅法,通过该⽅法可以获取obj的namespace,⽐如default
type Indexers map[string]IndexFunc
// Indices maps a name to an Index
// key是索引的分类名,⽐如namespace
type Indices map[string]Index
按照如上关系,举例来说,在Indicies中找到namespace的index,再从Index中找到 default 的所有pod的key,最后通过这些key可以从item中获取pod信息
结合下图。Indexer和Indices都可以进行索引查询,举例如下
- indexer:查询key为Namespace,返回func,通过func计算出
Index;再去Items理查询获取到obj。 - Indicies: 查询key为 Namespace,获取到对应的
Index; 再查询为default的所有结果,放到Items里就能获取到所有的pod对象( object
更新索引: updateIndices
更新流程举例:
以 threadSafeMap为例,
func (c *threadSafeMap) Add(key string, obj interface{}) {
c.Update(key, obj)
}
func (c *threadSafeMap) Update(key string, obj interface{}) {
c.lock.Lock()
defer c.lock.Unlock()
oldObject := c.items[key]
c.items[key] = obj
c.updateIndices(oldObject, obj, key)
}
关键在于updateIndices,这里可以看到更新的过程
// updateIndices modifies the objects location in the managed indexes:
// - for create you must provide only the newObj
// - for update you must provide both the oldObj and the newObj
// - for delete you must provide only the oldObj
// updateIndices must be called from a function that already has a lock on the cache
func (c *threadSafeMap) updateIndices(oldObj interface{}, newObj interface{}, key string) {
var oldIndexValues, indexValues []string
var err error
for name, indexFunc := range c.indexers {
if oldObj != nil {
oldIndexValues, err = indexFunc(oldObj)
} else {
// [:0] 相当于取了一个空slice
oldIndexValues = oldIndexValues[:0]
}
if err != nil {
panic(fmt.Errorf("unable to calculate an index entry for key %q on index %q: %v", key, name, err))
}
if newObj != nil {
indexValues, err = indexFunc(newObj)
} else {
indexValues = indexValues[:0]
}
if err != nil {
panic(fmt.Errorf("unable to calculate an index entry for key %q on index %q: %v", key, name, err))
}
index := c.indices[name]
if index == nil {
index = Index{}
c.indices[name] = index
}
if len(indexValues) == 1 && len(oldIndexValues) == 1 && indexValues[0] == oldIndexValues[0] {
// We optimize for the most common case where indexFunc returns a single value which has not been changed
continue
}
for _, value := range oldIndexValues {
c.deleteKeyFromIndex(key, value, index)
}
for _, value := range indexValues {
c.addKeyToIndex(key, value, index)
}
}
}
参考
部分图片参考自:www.bilibili.com/video/BV15m…