πŸš€ Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more β†’
Socket
Sign inDemoInstall
Socket

redis_counters

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

redis_counters

1.5.2
Rubygems
Version published
Maintainers
1
Created
Source

RedisCounters

Build Status Code Climate Test Coverage

Набор структур Π΄Π°Π½Π½Ρ‹Ρ… Π½Π° Π±Π°Π·Π΅ Redis.

RedisCounters::HashCounter

Π‘Ρ‡Π΅Ρ‚Ρ‡ΠΈΠΊ Π½Π° основС Hash, с прСфСрансом ΠΈ Ρ‚Π°ΠΉΠΊΠ°ΠΌΠΈ-близняшками ΠΏΠ°Ρ€Ρ‚ΠΈΡ†ΠΈΠΎΠ½ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΠΈ кластСризациСй Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ.

ΠžΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹: counter_name, field_name ΠΈΠ»ΠΈ group_keys.

Π‘Π»ΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ

  • ΠΈΠ½ΠΊΡ€Π΅ΠΌΠ΅Π½Ρ‚ - O(1).

ΠŸΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ использования

ΠŸΡ€ΠΎΡΡ‚ΠΎΠΉ счСтчик Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ.

counter = RedisCounters::HashCounter.new(redis, {
  :counter_name => :simple_counter,
  :field_name   => :pages
})

5.times { counter.increment }

redis:
  simple_counter = {
    pages => 5
  }

> counter.partitions
=> [{}]

> counter.data
=> [{:value=>5}]

Π‘Ρ‡Π΅Ρ‚Ρ‡ΠΈΠΊ посСщСнных страниц ΠΊΠΎΠΌΠΏΠ°Π½ΠΈΠΈ с ΠΏΠ°Ρ€Ρ‚ΠΈΡ†ΠΈΠΎΠ½ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΠΏΠΎ Π΄Π°Ρ‚Π΅.

counter = RedisCounters::HashCounter.new(redis, {
  :counter_name   => :pages_by_day,
  :group_keys     => [:company_id],
  :partition_keys => [:date]
})

2.times { counter.increment(:company_id => 1, :date => '2013-08-01') }
3.times { counter.increment(:company_id => 2, :date => '2013-08-01') }
1.times { counter.increment(:company_id => 3, :date => '2013-08-02') }

redis:
  pages_by_day:2013-08-01 = {
    1 => 2
    2 => 3
  }
  pages_by_day:2013-08-02 = {
    3 => 1
  }

> counter.partitions
=> [{:date=>"2013-08-01"}, {:date=>"2013-08-02"}]

> counter.data
=> [{:company_id=>"1", :value=>2},
 {:company_id=>"2", :value=>3},
 {:company_id=>"3", :value=>1}]

> counter.delete_partitions!(:date => '2013-08-01')
=> [1]

> counter.partitions
=> [{:date=>"2013-08-02"}]

> counter.data
=> [{:company_id=>"3", :value=>1}]

> counter.delete_all!
=> [1]

> counter.data
=> []

Π’ΠΎΠΆΠ΅ самоС, Π½ΠΎ партиция задаСтся с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ proc.

counter = RedisCounters::HashCounter.new(redis, {
  :counter_name   => :pages_by_day,
  :group_keys     => [:company_id],
  :partition_keys => proc { |params| params.fetch(:date) }
})

Π‘Ρ‡Π΅Ρ‚Ρ‡ΠΈΠΊ посСщСнных страниц с Π³Ρ€ΡƒΠΏΠΏΠΈΡ€ΠΎΠ²ΠΊΠΎΠΉ ΠΏΠΎ Π³ΠΎΡ€ΠΎΠ΄Ρƒ посСтитСля ΠΈ ΠΏΠ°Ρ€Ρ‚ΠΈΡ†ΠΈΠΎΠ½ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΠΏΠΎ Π΄Π°Ρ‚Π΅ ΠΈ ΠΊΠΎΠΌΠΏΠ°Π½ΠΈΠΈ.

counter = RedisCounters::HashCounter.new(redis, {
  :counter_name   => :pages_by_day_city,
  :group_keys     => [:company_id, :city_id],
  :partition_keys => [:date, :company_id]
})

2.times { counter.increment(:date => '2013-08-01', :company_id => 1, :city_id => 11) }
1.times { counter.increment(:date => '2013-08-01', :company_id => 1, :city_id => 12) }
4.times { counter.increment(:date => '2013-08-01', :company_id => 2, :city_id => 10) }
3.times { counter.increment(:date => '2013-08-02', :company_id => 1, :city_id => 15) }

redis:
  pages_by_day_city:2013-08-01:1 = {
    1:11 => 2,
    1:12 => 1
  }

  pages_by_day_city:2013-08-01:2 = {
    2:10 => 4
  }

  pages_by_day_city:2013-08-02:1 = {
    1:15 => 3
  }

> counter.partitions
=> [{:date=>"2013-08-02", :company_id=>"1"},
 {:date=>"2013-08-01", :company_id=>"1"},
 {:date=>"2013-08-01", :company_id=>"2"}]

> counter.partitions(:date => '2013-08-01')
=> [{:date=>"2013-08-01", :company_id=>"1"},
 {:date=>"2013-08-01", :company_id=>"2"}]

> counter.data
=> [{:company_id => 1, :city_id=>"15", :value=>3},
 {:company_id => 1, :city_id=>"11", :value=>2},
 {:company_id => 1, :city_id=>"12", :value=>1},
 {:company_id => 2, :city_id=>"10", :value=>4}]

> counter.data(:date => '2013-08-01')
=> [{:company_id => 1, :city_id=>"11", :value=>2},
 {:company_id => 1, :city_id=>"12", :value=>1},
 {:company_id => 2, :city_id=>"10", :value=>4}]

> counter.data(:date => '2013-08-01') { |batch| puts batch }
{:company_id => 1, :city_id=>"11", :value=>2}
{:company_id => 1, :city_id=>"12", :value=>1}
{:company_id => 2, :city_id=>"10", :value=>4}

RedisCounters::UniqueValuesLists::Blocking

Бписок ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹Ρ… Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ, с Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒΡŽ кластСризации ΠΈ партиционирования Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ.

ΠžΡΠΎΠ±Π΅Π½Π½ΠΎΡΡ‚ΠΈ:

  • Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ оптимистичных Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΎΠΊ.
  • Помимо списка Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ, Π²Π΅Π΄Π΅Ρ‚ Ρ‚Π°ΠΊ ΠΆΠ΅, список ΠΏΠ°Ρ€Ρ‚ΠΈΡ†ΠΈΠΉ, для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ кластСра.
  • ΠŸΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΎΠ½Π΅Π½ - сторонний Π±Π»ΠΎΠΊ, выполняСмый послС добавлСния ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½ΠΎΠ³ΠΎ элСмСнта, выполняСтся Π² Ρ‚ΠΎΠΉ ΠΆΠ΅ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ добавляСтся ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ элСмСнт.

ВСроятно, Π² условиях большой конкурСнтности, ΠΎΠ±Π»Π°Π΄Π°Π΅Ρ‚ Π½Π΅ Π»ΡƒΡ‡ΡˆΠ΅ΠΉ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡŒΡŽ ΠΈΠ·-Π·Π° частых Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΎΠΊ.

ΠžΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹: counter_name ΠΈ value_keys.

Π‘Π»ΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ

  • Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ элСмСнта - ΠΎΡ‚ O(1), ΠΏΡ€ΠΈ отсутствии партиционирования, Π΄ΠΎ O(N), Π³Π΄Π΅ N - ΠΊΠΎΠ»-Π²ΠΎ ΠΏΠ°Ρ€Ρ‚ΠΈΡ†ΠΈΠΉ.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ использования

ΠŸΡ€ΠΎΡΡ‚ΠΎΠΉ список ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹Ρ… ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ.

counter = RedisCounters::UniqueValuesLists::Blocking.new(redis, {
  :counter_name => :users,
  :value_keys   => [:user_id]
})

counter.increment(:user_id => 1)
counter.increment(:user_id => 2)
counter.increment(:user_id => 1)

redis:
  users = ['1', '2']

Бписок ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹Ρ… ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ, ΠΏΠΎΡΠ΅Ρ‚ΠΈΠ²ΡˆΠΈΡ… компаниию, Π·Π° мСсяц, ΠΏΠ°Ρ€Ρ‚ΠΈΡ†ΠΈΠΎΠ½ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ ΠΏΠΎ суткам.

counter = RedisCounters::UniqueValuesLists::Blocking.new(redis, {
  :counter_name   => :company_users_by_month,
  :value_keys     => [:company_id, :user_id],
  :cluster_keys   => [:start_month_date],
  :partition_keys => [:date]
})

2.times { counter.add(:company_id => 1, :user_id => 11, :date => '2013-08-10', :start_month_date => '2013-08-01') }
3.times { counter.add(:company_id => 1, :user_id => 22, :date => '2013-08-10', :start_month_date => '2013-08-01') }
3.times { counter.add(:company_id => 1, :user_id => 22, :date => '2013-09-05', :start_month_date => '2013-09-01') }
3.times { counter.add(:company_id => 2, :user_id => 11, :date => '2013-08-10', :start_month_date => '2013-08-01') }
1.times { counter.add(:company_id => 2, :user_id => 22, :date => '2013-08-11', :start_month_date => '2013-08-01') }

redis:
  company_users_by_month:2013-08-01:partitions = ['2013-08-10', '2013-08-11']
  company_users_by_month:2013-08-01:2013-08-10 = ['1:11', '1:22', '2:11']
  company_users_by_month:2013-08-01:2013-08-11 = ['2:22']

  company_users_by_month:2013-09-01:partitions = ['2013-09-05']
  company_users_by_month:2013-09-01:2013-09-05 = ['1:22']

RedisCounters::UniqueValuesLists::NonBlocking

Быстрый список ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹Ρ… Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ, с Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒΡŽ кластСризации ΠΈ партиционирования Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ.

Π‘ΠΊΠΎΡ€ΠΎΡΡ‚ΡŒ Ρ€Π°Π±ΠΎΡ‚Ρ‹ достигаСтся Π·Π° счСт ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΡ… особСнностСй:

  • Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ 2Ρ… объСма памяти для хранСния элСмСнтов, ΠΏΡ€ΠΈ использовании партиционирования. Eсли ΠΏΠ°Ρ€Ρ‚ΠΈΡ†ΠΈΠΎΠ½ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ, Ρ‚ΠΎ расход памяти Ρ‚Π°ΠΊΠΎΠΉ-ΠΆΠ΅ ΠΊΠ°ΠΊ Ρƒ UniqueValuesLists::Blocking.
  • НС Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΎΠ½Π΅Π½ - сторонний Π±Π»ΠΎΠΊ, выполняСмый послС добавлСния ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½ΠΎΠ³ΠΎ элСмСнта, выполняСтся Π·Π° ΠΏΡ€Π΅Π΄Π΅Π»Π°ΠΌΠΈ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ добавляСтся ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ элСмСнт.
  • НС вСдСтся список ΠΏΠ°Ρ€Ρ‚ΠΈΡ†ΠΈΠΉ.

ΠžΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹: counter_name ΠΈ value_keys.

Π‘Π»ΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ

  • Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ элСмСнта - O(1)

RedisCounters::UniqueValuesLists::Expirable

Бписок ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹Ρ… Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ, с Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒΡŽ expire ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹Ρ… элСмСнтов.

На основС сортированного мноТСства. http://redis4you.com/code.php?id=010

На основС ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΠ° оптимистичСских Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΎΠΊ. смотри Optimistic locking using check-and-set: http://redis.io/topics/transactions

ΠžΡΠΎΠ±Π΅Π½Π½ΠΎΡΡ‚ΠΈ:

  • Expire - Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚, ΠΌΠΎΠΆΠ½ΠΎ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ΠΊΠ°ΠΊ Π½Π° ΡƒΡ€ΠΎΠ²Π½Π΅ счСтчика, Ρ‚Π°ΠΊ ΠΈ Π½Π° ΡƒΡ€ΠΎΠ²Π½Π΅ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠ³ΠΎ занчСния;
  • ΠžΡ‡ΠΈΡΡ‚ΠΊΠ° Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Π° ΠΊΠ°ΠΊ Π² автоматичСскогом Ρ€Π΅ΠΆΠΈΠΌΠ΅ Ρ‚Π°ΠΊ Π² ΠΈ Ρ€ΡƒΡ‡Π½ΠΎΠΌ;
  • ЗначСния сохраняСт Π² партициях;
  • Π’Π΅Π΄Π΅Ρ‚ список ΠΏΠ°Ρ€Ρ‚ΠΈΡ†ΠΈΠΉ;
  • ΠŸΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΎΠ½Π΅Π½.

ΠžΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹: counter_name ΠΈ value_keys. Π’Π°ΠΉΠΌΠ°ΡƒΡ‚ задаСтся ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠΌ :expire. По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ :never. :clean_expired - Ρ€Π΅ΠΆΠΈΠΌ автоочистки. По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ true.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ использования

counter = RedisCounters::UniqueValuesLists::Expirable.new(redis,
  :counter_name => :sessions,
  :value_keys   => [:session_id],
  :expire       => 10.minutes
)

counter << session_id: 1
counter << session_id: 2
counter << session_id: 3, expire: :never

counter.data
> [{session_id: 1}, {session_id: 2}, {session_id: 3}]

# after 10 minutes

counter.data
> [{session_id: 3}]

counter.has_value?(session_id: 1)
false

RedisCounters::UniqueHashCounter

Бборная конструкция Π½Π° основС ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΡ…. HashCounter, с Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒΡŽ подсчСта Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρƒ ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹Ρ… событий.

Π‘Π»ΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ

Π°Π½Π°Π»ΠΎΠ³ΠΈΡ‡Π½ΠΎ слоТности, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΠΎΠ³ΠΎ ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½ΠΎΠ³ΠΎ списка.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ использования

Π‘Ρ‡Π΅Ρ‚Ρ‡ΠΈΠΊ ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹Ρ… ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ, ΠΏΠΎΡΠ΅Ρ‚ΠΈΠ²ΡˆΠΈΡ… компаниию, Π·Π° мСсяц, кластСризованный ΠΏΠΎ суткам.

counter = RedisCounters::UniqueHashCounter.new(redis, {
  :counter_name   => :company_users_by_month,
  :group_keys     => [:company_id],
  :partition_keys => [:date],
  :unique_list => {
    :list_class     => RedisCounters::UniqueValuesLists::Blocking
    :value_keys     => [:company_id, :user_id],
    :cluster_keys   => [:start_month_date],
    :partition_keys => [:date]
  }
})

2.times { counter.increment(:company_id => 1, :user_id => 11, :date => '2013-08-10', :start_month_date => '2013-08-01') }
3.times { counter.increment(:company_id => 1, :user_id => 22, :date => '2013-08-10', :start_month_date => '2013-08-01') }
3.times { counter.increment(:company_id => 1, :user_id => 22, :date => '2013-09-05', :start_month_date => '2013-09-01') }
3.times { counter.increment(:company_id => 2, :user_id => 11, :date => '2013-08-10', :start_month_date => '2013-08-01') }
1.times { counter.increment(:company_id => 2, :user_id => 22, :date => '2013-08-11', :start_month_date => '2013-08-01') }

redis:
  company_users_by_month:2013-08-10 = {
    1 = 2,
    2 = 1
  }
  company_users_by_month:2013-08-11 = {
    2 = 1
  }
  company_users_by_month:2013-09-05 = {
    1 = 1
  }

  company_users_by_month_uq:2013-08-01:partitions = ['2013-08-10', '2013-08-11']
  company_users_by_month_uq:2013-08-01:2013-08-10 = ['1:11', '1:22', '2:11']
  company_users_by_month_uq:2013-08-01:2013-08-11 = ['2:22']

  company_users_by_month_uq:2013-09-01:partitions = ['2013-09-05']
  company_users_by_month_uq:2013-09-01:2013-09-05 = ['1:22']

FAQs

Package last updated on 05 May 2022

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts